svn update: 48958 (latest:48959)
authorYoumin Ha <youmin.ha@samsung.com>
Tue, 18 May 2010 07:15:55 +0000 (16:15 +0900)
committerYoumin Ha <youmin.ha@samsung.com>
Tue, 18 May 2010 07:15:55 +0000 (16:15 +0900)
326 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
COPYING-PLAIN [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README.in [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
debian/SVN_REV [new file with mode: 0644]
debian/_original/changelog [new file with mode: 0644]
debian/_original/compat [new file with mode: 0644]
debian/_original/control [new file with mode: 0644]
debian/_original/copyright [new file with mode: 0644]
debian/_original/ecore_config.1 [new file with mode: 0644]
debian/_original/libecore-bin.install [new file with mode: 0644]
debian/_original/libecore-con-svn-01.install [new file with mode: 0644]
debian/_original/libecore-con-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-config-svn-01.install [new file with mode: 0644]
debian/_original/libecore-config-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-dev.install [new file with mode: 0644]
debian/_original/libecore-doc.doc-base [new file with mode: 0644]
debian/_original/libecore-evas-svn-01.install [new file with mode: 0644]
debian/_original/libecore-evas-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-fb-svn-01.install [new file with mode: 0644]
debian/_original/libecore-fb-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-file-svn-01.install [new file with mode: 0644]
debian/_original/libecore-file-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-imf-svn-01.install [new file with mode: 0644]
debian/_original/libecore-imf-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-input-svn-01.install [new file with mode: 0644]
debian/_original/libecore-input-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-ipc-svn-01.install [new file with mode: 0644]
debian/_original/libecore-ipc-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-svn-01.install [new file with mode: 0644]
debian/_original/libecore-svn-01.shlibs [new file with mode: 0644]
debian/_original/libecore-x-svn-01.install [new file with mode: 0644]
debian/_original/libecore-x-svn-01.shlibs [new file with mode: 0644]
debian/_original/rules [new file with mode: 0755]
doc/.cvsignore [new file with mode: 0644]
doc/Doxyfile [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/e.css [new file with mode: 0644]
doc/ecore.dox.in [new file with mode: 0644]
doc/foot.html [new file with mode: 0644]
doc/head.html [new file with mode: 0644]
doc/img/e.png [new file with mode: 0644]
doc/img/edoxy.css [new file with mode: 0644]
doc/img/elementary.png [new file with mode: 0644]
doc/img/foot_bg.png [new file with mode: 0644]
doc/img/head_bg.png [new file with mode: 0644]
doc/img/header_menu_background.png [new file with mode: 0644]
doc/img/header_menu_background_last.png [new file with mode: 0644]
doc/img/header_menu_current_background.png [new file with mode: 0644]
doc/img/header_menu_unselected_background.png [new file with mode: 0644]
doc/img/logo.png [new file with mode: 0644]
doc/img/prog_flow.png [new file with mode: 0644]
ecore-cocoa.pc.in [new file with mode: 0644]
ecore-con.pc.in [new file with mode: 0644]
ecore-config.pc.in [new file with mode: 0644]
ecore-directfb.pc.in [new file with mode: 0644]
ecore-evas.pc.in [new file with mode: 0644]
ecore-fb.pc.in [new file with mode: 0644]
ecore-file.pc.in [new file with mode: 0644]
ecore-imf-evas.pc.in [new file with mode: 0644]
ecore-imf.pc.in [new file with mode: 0644]
ecore-input-evas.pc.in [new file with mode: 0644]
ecore-input.pc.in [new file with mode: 0644]
ecore-ipc.pc.in [new file with mode: 0644]
ecore-job.pc.in [new file with mode: 0644]
ecore-sdl.pc.in [new file with mode: 0644]
ecore-win32.pc.in [new file with mode: 0644]
ecore-wince.pc.in [new file with mode: 0644]
ecore-x.pc.in [new file with mode: 0644]
ecore.pc.in [new file with mode: 0644]
ecore.spec.in [new file with mode: 0644]
ecore.supp [new file with mode: 0644]
m4/ac_abstract_socket.m4 [new file with mode: 0644]
m4/ac_attribute.m4 [new file with mode: 0644]
m4/check_x_extension.m4 [new file with mode: 0644]
m4/ecore_check_module.m4 [new file with mode: 0644]
m4/ecore_check_options.m4 [new file with mode: 0644]
m4/efl_doxygen.m4 [new file with mode: 0644]
m4/efl_path_max.m4 [new file with mode: 0644]
m4/efl_pthread.m4 [new file with mode: 0644]
m4/efl_tests.m4 [new file with mode: 0644]
po/ChangeLog [new file with mode: 0644]
po/LINGUAS [new file with mode: 0644]
po/Makevars [new file with mode: 0644]
po/POTFILES.in [new file with mode: 0644]
po/cs.po [new file with mode: 0644]
po/de.po [new file with mode: 0644]
po/el.po [new file with mode: 0644]
po/fr.po [new file with mode: 0644]
po/it.po [new file with mode: 0644]
src/.cvsignore [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/bin/.cvsignore [new file with mode: 0644]
src/bin/Makefile.am [new file with mode: 0644]
src/bin/ecore_config.c [new file with mode: 0644]
src/lib/.cvsignore [new file with mode: 0644]
src/lib/Makefile.am [new file with mode: 0644]
src/lib/ecore/.cvsignore [new file with mode: 0644]
src/lib/ecore/Ecore.h [new file with mode: 0644]
src/lib/ecore/Ecore_Getopt.h [new file with mode: 0644]
src/lib/ecore/Makefile.am [new file with mode: 0644]
src/lib/ecore/ecore.c [new file with mode: 0644]
src/lib/ecore/ecore_anim.c [new file with mode: 0644]
src/lib/ecore/ecore_app.c [new file with mode: 0644]
src/lib/ecore/ecore_events.c [new file with mode: 0644]
src/lib/ecore/ecore_exe.c [new file with mode: 0644]
src/lib/ecore/ecore_exe_win32.c [new file with mode: 0644]
src/lib/ecore/ecore_exe_wince.c [new file with mode: 0644]
src/lib/ecore/ecore_getopt.c [new file with mode: 0644]
src/lib/ecore/ecore_glib.c [new file with mode: 0644]
src/lib/ecore/ecore_idle_enterer.c [new file with mode: 0644]
src/lib/ecore/ecore_idle_exiter.c [new file with mode: 0644]
src/lib/ecore/ecore_idler.c [new file with mode: 0644]
src/lib/ecore/ecore_job.c [new file with mode: 0644]
src/lib/ecore/ecore_main.c [new file with mode: 0644]
src/lib/ecore/ecore_pipe.c [new file with mode: 0644]
src/lib/ecore/ecore_poll.c [new file with mode: 0644]
src/lib/ecore/ecore_private.h [new file with mode: 0644]
src/lib/ecore/ecore_signal.c [new file with mode: 0644]
src/lib/ecore/ecore_thread.c [new file with mode: 0644]
src/lib/ecore/ecore_time.c [new file with mode: 0644]
src/lib/ecore/ecore_timer.c [new file with mode: 0644]
src/lib/ecore_cocoa/Ecore_Cocoa.h [new file with mode: 0644]
src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h [new file with mode: 0644]
src/lib/ecore_cocoa/Makefile.am [new file with mode: 0644]
src/lib/ecore_cocoa/ecore_cocoa.m [new file with mode: 0644]
src/lib/ecore_cocoa/ecore_cocoa_private.h [new file with mode: 0644]
src/lib/ecore_cocoa/ecore_cocoa_window.m [new file with mode: 0644]
src/lib/ecore_con/.cvsignore [new file with mode: 0644]
src/lib/ecore_con/Ecore_Con.h [new file with mode: 0644]
src/lib/ecore_con/Makefile.am [new file with mode: 0644]
src/lib/ecore_con/ecore_con.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_ares.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_info.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_local.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_private.h [new file with mode: 0644]
src/lib/ecore_con/ecore_con_ssl.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_url.c [new file with mode: 0644]
src/lib/ecore_config/.cvsignore [new file with mode: 0644]
src/lib/ecore_config/Ecore_Config.h [new file with mode: 0644]
src/lib/ecore_config/Makefile.am [new file with mode: 0644]
src/lib/ecore_config/ecore_config.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_db.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_extra.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_ipc.h [new file with mode: 0644]
src/lib/ecore_config/ecore_config_ipc_ecore.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_ipc_main.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_private.h [new file with mode: 0644]
src/lib/ecore_config/ecore_config_storage.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_util.c [new file with mode: 0644]
src/lib/ecore_config/ecore_config_util.h [new file with mode: 0644]
src/lib/ecore_directfb/.cvsignore [new file with mode: 0644]
src/lib/ecore_directfb/Ecore_DirectFB.h [new file with mode: 0644]
src/lib/ecore_directfb/Makefile.am [new file with mode: 0644]
src/lib/ecore_directfb/ecore_directfb.c [new file with mode: 0644]
src/lib/ecore_directfb/ecore_directfb_keys.h [new file with mode: 0644]
src/lib/ecore_directfb/ecore_directfb_private.h [new file with mode: 0644]
src/lib/ecore_evas/.cvsignore [new file with mode: 0644]
src/lib/ecore_evas/Ecore_Evas.h [new file with mode: 0644]
src/lib/ecore_evas/Makefile.am [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_buffer.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_cocoa.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_directfb.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_fb.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_private.h [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_sdl.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_util.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_win32.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_wince.c [new file with mode: 0644]
src/lib/ecore_evas/ecore_evas_x.c [new file with mode: 0644]
src/lib/ecore_fb/.cvsignore [new file with mode: 0644]
src/lib/ecore_fb/Ecore_Fb.h [new file with mode: 0644]
src/lib/ecore_fb/Makefile.am [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb.c [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_kbd.c [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_keytable.h [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_li.c [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_private.h [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_ps2.c [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_ts.c [new file with mode: 0644]
src/lib/ecore_fb/ecore_fb_vt.c [new file with mode: 0644]
src/lib/ecore_file/.cvsignore [new file with mode: 0644]
src/lib/ecore_file/Ecore_File.h [new file with mode: 0644]
src/lib/ecore_file/Makefile.am [new file with mode: 0644]
src/lib/ecore_file/ecore_file.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_download.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_monitor.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_monitor_inotify.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_monitor_poll.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_monitor_win32.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_path.c [new file with mode: 0644]
src/lib/ecore_file/ecore_file_private.h [new file with mode: 0644]
src/lib/ecore_imf/.cvsignore [new file with mode: 0644]
src/lib/ecore_imf/Ecore_IMF.h [new file with mode: 0644]
src/lib/ecore_imf/Makefile.am [new file with mode: 0644]
src/lib/ecore_imf/ecore_imf.c [new file with mode: 0644]
src/lib/ecore_imf/ecore_imf_context.c [new file with mode: 0644]
src/lib/ecore_imf/ecore_imf_module.c [new file with mode: 0644]
src/lib/ecore_imf/ecore_imf_private.h [new file with mode: 0644]
src/lib/ecore_imf_evas/.cvsignore [new file with mode: 0644]
src/lib/ecore_imf_evas/Ecore_IMF_Evas.h [new file with mode: 0644]
src/lib/ecore_imf_evas/Makefile.am [new file with mode: 0644]
src/lib/ecore_imf_evas/ecore_imf_evas.c [new file with mode: 0644]
src/lib/ecore_input/Ecore_Input.h [new file with mode: 0644]
src/lib/ecore_input/Makefile.am [new file with mode: 0644]
src/lib/ecore_input/ecore_input.c [new file with mode: 0644]
src/lib/ecore_input/ecore_input_private.h [new file with mode: 0644]
src/lib/ecore_input_evas/Ecore_Input_Evas.h [new file with mode: 0644]
src/lib/ecore_input_evas/Makefile.am [new file with mode: 0644]
src/lib/ecore_input_evas/ecore_input_evas.c [new file with mode: 0644]
src/lib/ecore_input_evas/ecore_input_evas_private.h [new file with mode: 0644]
src/lib/ecore_ipc/.cvsignore [new file with mode: 0644]
src/lib/ecore_ipc/Ecore_Ipc.h [new file with mode: 0644]
src/lib/ecore_ipc/Makefile.am [new file with mode: 0644]
src/lib/ecore_ipc/ecore_ipc.c [new file with mode: 0644]
src/lib/ecore_ipc/ecore_ipc_private.h [new file with mode: 0644]
src/lib/ecore_sdl/.cvsignore [new file with mode: 0644]
src/lib/ecore_sdl/Ecore_Sdl.h [new file with mode: 0644]
src/lib/ecore_sdl/Ecore_Sdl_Keys.h [new file with mode: 0644]
src/lib/ecore_sdl/Makefile.am [new file with mode: 0644]
src/lib/ecore_sdl/ecore_sdl.c [new file with mode: 0644]
src/lib/ecore_sdl/ecore_sdl_private.h [new file with mode: 0644]
src/lib/ecore_win32/.cvsignore [new file with mode: 0644]
src/lib/ecore_win32/Ecore_Win32.h [new file with mode: 0644]
src/lib/ecore_win32/Makefile.am [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32.c [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_cursor.c [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd.c [new file with mode: 0755]
src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_data_object.h [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_drop_source.h [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_drop_target.h [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_event.c [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_private.h [new file with mode: 0644]
src/lib/ecore_win32/ecore_win32_window.c [new file with mode: 0644]
src/lib/ecore_wince/.cvsignore [new file with mode: 0644]
src/lib/ecore_wince/Ecore_WinCE.h [new file with mode: 0644]
src/lib/ecore_wince/Makefile.am [new file with mode: 0644]
src/lib/ecore_wince/ecore_wince.c [new file with mode: 0644]
src/lib/ecore_wince/ecore_wince_event.c [new file with mode: 0644]
src/lib/ecore_wince/ecore_wince_private.h [new file with mode: 0644]
src/lib/ecore_wince/ecore_wince_window.c [new file with mode: 0644]
src/lib/ecore_x/.cvsignore [new file with mode: 0644]
src/lib/ecore_x/Ecore_X.h [new file with mode: 0644]
src/lib/ecore_x/Ecore_X_Atoms.h [new file with mode: 0644]
src/lib/ecore_x/Ecore_X_Cursor.h [new file with mode: 0644]
src/lib/ecore_x/Makefile.am [new file with mode: 0644]
src/lib/ecore_x/ecore_x_atoms_decl.h [new file with mode: 0644]
src/lib/ecore_x/xcb/.cvsignore [new file with mode: 0644]
src/lib/ecore_x/xcb/Makefile.am [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_atom.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_composite.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_cursor.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_damage.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_dnd.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_dpms.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_drawable.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_e.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_events.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_fixes.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_gc.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_icccm.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_mwm.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_netwm.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_pixmap.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_private.h [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_randr.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_region.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_reply.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_screensaver.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_selection.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_shape.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_sync.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_window.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_window_prop.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c [new file with mode: 0644]
src/lib/ecore_x/xcb/ecore_xcb_xinerama.c [new file with mode: 0644]
src/lib/ecore_x/xlib/.cvsignore [new file with mode: 0644]
src/lib/ecore_x/xlib/Makefile.am [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_atoms.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_composite.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_cursor.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_damage.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_dnd.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_dpms.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_drawable.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_e.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_error.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_events.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_fixes.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_gc.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_icccm.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_image.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_mwm.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_netwm.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_pixmap.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_private.h [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_randr.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_region.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_screensaver.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_selection.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_sync.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_test.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_window.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_window_prop.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_window_shape.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_xi2.c [new file with mode: 0644]
src/lib/ecore_x/xlib/ecore_x_xinerama.c [new file with mode: 0644]
src/tests/Makefile.am [new file with mode: 0644]
src/tests/ecore_suite.c [new file with mode: 0644]
src/tests/ecore_suite.h [new file with mode: 0644]
src/tests/ecore_test_ecore.c [new file with mode: 0644]
src/tests/ecore_test_ecore_con.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..4acdbfb
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,31 @@
+The Rasterman <raster@rasterman.com>
+Tom Gilbert <tom@linuxbrit.co.uk>
+Burra <burra@colorado.edu>
+Chris Ross <chris@darkrock.co.uk>
+Term <term@twistedpath.org>
+Tilman Sauerbeck <tilman@code-monkey.de>
+Ibukun Olumuyiwa <ibukun@computer.org>
+Yuri <da2001@hotmail.ru>
+Nicholas Curran <quasar@bigblue.net.au>
+Howell Tam <pigeon@pigeond.net>
+Nathan Ingersoll <rbdpngn@users.sourceforge.net>
+Andrew Elcock <andy@elcock.org>
+Kim Woelders <kim@woelders.dk>
+Sebastian Dransfeld <sebastid@tango.flipp.net>
+Simon Poole <simon.armlinux@themalago.net>
+Jorge Luis Zapata Muga <jorgeluis.zapata@gmail.com>
+dan sinclair <zero@everburning.com>
+Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+David 'onefang' Seikel <onefang@gmail.com>
+Hisham 'CodeWarrior' Mardam Bey <hisham@hisham.cc>
+Brian 'rephorm' Mattern <rephorm@rephorm.com>
+Tim Horton <hortont424@gmail.com>
+Arnaud de Turckheim 'quarium' <quarium@gmail.com>
+Matt Barclay <mbarclay@gmail.com>
+Peter Wehrfritz <peter.wehrfritz@web.de>
+Albin "Lutin" Tonnerre <albin.tonnerre@gmail.com>
+Vincent Torri <vincent.torri@gmail.com>
+Lars Munch <lars@segv.dk>
+Andre Dieb <andre.dieb@gmail.com>
+Mathieu Taillefumier <mathieu.taillefumier@free.fr>
+Rui Miguel Silva Seabra <rms@1407.org>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..dee3047
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+  
+The above copyright notice and this permission notice shall be included in
+all copies of the Software, its documentation and marketing & publicity 
+materials, and acknowledgment shall be given in the documentation, materials
+and software packages that this Software was used.
+   
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/COPYING-PLAIN b/COPYING-PLAIN
new file mode 100644 (file)
index 0000000..376875e
--- /dev/null
@@ -0,0 +1,33 @@
+Plain English Copyright Notice
+
+This file is not intended to be the actual License. The reason this file
+exists is that we here are programmers and engineers. We aren't lawyers. We
+provide licenses that we THINK say the right things, but we have our own
+intentions at heart. This is a plain-english explanation of what those
+intentions are, and if you follow them you will be within the "spirit" of
+the license.
+
+The intent is for us to enjoy writing software that is useful to us (the
+AUTHORS) and allow others to use it freely and also benefit from the work we
+put into making it. We don't want to restrict others using it. They should
+not *HAVE* to make the source code of the applications they write that
+simply link to these libraries (be that statically or dynamically), or for
+them to be limited as to what license they choose to use (be it open, closed
+or anything else). But we would like to know you are using these libraries.
+We simply would like to know that it has been useful to someone. This is why
+we ask for acknowledgement of some sort.
+
+You can do what you want with the source of this software - it doesn't
+matter. We still have it here for ourselves and it is open and free to use
+and download and play with. It can't be taken away. We don't really mind what
+you do with the source to your software. We would simply like to know that
+you are using it - especially if it makes it to a commerical product. If you
+simply e-mail all the AUTHORS (see COPYING and AUTHORS files) telling us, and
+then make sure you include a paragraph or page in the manual for the product
+with the copyright notice and state that you used this software, we will be
+very happy. If you want to contribute back modifications and fixes you may have
+made we will welcome those too with open arms (generally). If you want help
+with changes needed, ports needed or features to be added, arrangements can
+be easily made with some dialogue.
+
+Carsten Haitzler <raster@rasterman.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..ee16b53
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+Wed Jun  8 16:56:30 2005                        Michael Jennings (mej)
+
+Fix spec file.
+----------------------------------------------------------------------
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..3a3ad7e
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,14 @@
+COMPILING and INSTALLING:
+
+If you got a official release tar archive do:
+    ./configure
+    
+( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
+    
+Then to compile:
+    make
+
+To install (run this as root, or the user who handles installs):
+    make install
+
+NOTE: You MUST make install Eet for it to run properly.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..bbd57ee
--- /dev/null
@@ -0,0 +1,170 @@
+## Process this file with automake to produce Makefile.in
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = doc src po
+
+
+MAINTAINERCLEANFILES = \
+ABOUT-NLS \
+Makefile.in \
+aclocal.m4 \
+autom4te.cache \
+config.guess \
+config.h.in \
+config.h.in~ \
+config.rpath \
+config.sub \
+configure \
+depcomp \
+install-sh \
+ltmain.sh \
+missing \
+mkinstalldirs \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \
+$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc.tar.bz2 \
+m4/libtool.m4 \
+m4/lt~obsolete.m4 \
+m4/ltoptions.m4 \
+m4/ltsugar.m4 \
+m4/ltversion.m4 \
+m4/codeset.m4 \
+m4/gettext.m4 \
+m4/glibc21.m4 \
+m4/iconv.m4 \
+m4/intdiv0.m4 \
+m4/inttypes_h.m4 \
+m4/inttypes.m4 \
+m4/inttypes-pri.m4 \
+m4/isc-posix.m4 \
+m4/lcmessage.m4 \
+m4/lib-ld.m4 \
+m4/lib-link.m4 \
+m4/lib-prefix.m4 \
+m4/nls.m4 \
+m4/po.m4 \
+m4/progtest.m4 \
+m4/stdint_h.m4 \
+m4/uintmax_t.m4 \
+m4/ulonglong.m4 \
+po/boldquot.sed \
+po/en@boldquot.header \
+po/en@quot.header \
+po/insert-header.sin \
+po/Makefile.in.in \
+po/Makevars.template \
+po/quot.sed \
+po/remove-potcdate.sin \
+po/Rules-quot
+
+bin_SCRIPTS = 
+
+EXTRA_DIST = AUTHORS COPYING COPYING-PLAIN \
+            autogen.sh ecore.supp \
+            ecore.pc.in \
+            ecore-con.pc.in \
+            ecore-config.pc.in \
+            ecore-directfb.pc.in\
+            ecore-evas.pc.in \
+            ecore-fb.pc.in \
+            ecore-file.pc.in \
+            ecore-imf.pc.in \
+            ecore-imf-evas.pc.in \
+            ecore-ipc.pc.in \
+            ecore-x.pc.in \
+            ecore-win32.pc.in \
+            ecore-sdl.pc.in \
+            ecore-cocoa.pc.in \
+            ecore-input.pc.in \
+            ecore-wince.pc.in \
+            ecore.spec.in ecore.spec
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ecore.pc
+
+if BUILD_ECORE_CON
+pkgconfig_DATA += ecore-con.pc
+endif
+
+if BUILD_ECORE_CONFIG
+pkgconfig_DATA += ecore-config.pc
+endif
+
+if BUILD_ECORE_DIRECTFB
+pkgconfig_DATA += ecore-directfb.pc
+endif
+
+if BUILD_ECORE_EVAS
+pkgconfig_DATA += ecore-evas.pc
+endif
+
+if BUILD_ECORE_FB
+pkgconfig_DATA += ecore-fb.pc
+endif
+
+if BUILD_ECORE_FILE
+pkgconfig_DATA += ecore-file.pc
+endif
+
+if BUILD_ECORE_IMF
+pkgconfig_DATA += ecore-imf.pc
+endif
+
+if BUILD_ECORE_IMF_EVAS
+pkgconfig_DATA += ecore-imf-evas.pc
+endif
+
+if BUILD_ECORE_INPUT
+pkgconfig_DATA += ecore-input.pc
+endif
+
+if BUILD_ECORE_INPUT_EVAS
+pkgconfig_DATA += ecore-input-evas.pc
+endif
+
+if BUILD_ECORE_IPC
+pkgconfig_DATA += ecore-ipc.pc
+endif
+
+if BUILD_ECORE_X
+pkgconfig_DATA += ecore-x.pc
+endif
+
+if BUILD_ECORE_WIN32
+pkgconfig_DATA += ecore-win32.pc
+endif
+
+if BUILD_ECORE_WINCE
+pkgconfig_DATA += ecore-wince.pc
+endif
+
+if BUILD_ECORE_SDL
+pkgconfig_DATA += ecore-sdl.pc
+endif
+
+if BUILD_ECORE_COCOA
+pkgconfig_DATA += ecore-cocoa.pc
+endif
+
+.PHONY: doc
+
+# Documentation
+
+doc:
+       @echo "entering doc/"
+       make -C doc doc
+
+# Unit tests
+
+if EFL_ENABLE_TESTS
+
+check-local:
+       @./src/tests/ecore_suite
+
+else
+
+check-local:
+       @echo "reconfigure with --enable-tests"
+
+endif
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README.in b/README.in
new file mode 100644 (file)
index 0000000..58e2c48
--- /dev/null
+++ b/README.in
@@ -0,0 +1,71 @@
+Ecore @VERSION@
+
+Requirements:
+-------------
+
+Must:
+  libc libm
+
+Recommended:
+  libX11 libXext libXcursor libXprint libXinerama libXrandr libXss libXrender
+  libXcomposite libXfixes libXdamage libXdpms libXtest OpenSSL CURL
+
+Optional:
+  XCB SDL DirectFB
+
+Ecore is a clean and tiny event loop library with many modules to do
+lots of convenient things for a programmer, to save time and effort.
+
+It's small and lean, designed to work on embedded systems all the way
+to large and powerful multi-cpu workstations. It serialises all system
+signals, events etc. into a single event queue, that is easily
+processed without needing to worry about concurrency. A properly
+written, event-driven program using this kind of programming doesn't
+need threads, nor has to worry about concurrency. It turns a program
+into a state machine, and makes it very robust and easy to follow.
+
+Ecore gives you other handy primitives, such as timers to tick over
+for you and call specified functions at particular times so the
+programmer can use this to do things, like animate, or time out on
+connections or tasks that take too long etc.
+
+Idle handlers are provided too, as well as calls on entering an idle
+state (often a very good time to update the state of the program). All
+events that enter the system are passed to specific callback functions
+that the program sets up to handle those events. Handling them is
+simple and other Ecore modules produce more events on the queue,
+coming from other sources such as file descriptors etc.
+
+Ecore also lets you have functions called when file descriptors become
+active for reading or writing, allowing for streamlined, non-blocking
+IO.
+
+------------------------------------------------------------------------------
+COMPILING AND INSTALLING:
+
+  ./configure
+  make
+(as root unless youa re installing in your users directories):
+  make install
+      
+------------------------------------------------------------------------------
+BUILDING PACKAGES:
+
+RPM: To build rpm packages:
+  
+  sudo rpm -ta @PACKAGE@-@VERSION@.tar.gz
+
+You will find rpm packages in your system /usr/src/redhat/* dirs (note you may
+not need to use sudo or root if you have your own ~/.rpmrc. see rpm documents
+for more details)
+
+DEB: To build deb packages:
+
+  tar zvf @PACKAGE@-@VERSION@.tar.gz
+  cd @PACKAGE@-@VERSION@
+  dpkg-buildpackage -us -uc -rfakeroot
+  cd ..
+  rm -rf @PACKAGE@-@VERSION@
+
+You will find all the debian source, binary etc. packages put in the directory
+where you first untarred the source tarball.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..0a59462
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+
+touch README
+
+echo "Running autopoint..." ; autopoint -f || :
+echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1
+echo "Running autoheader..." ; autoheader || exit 1
+echo "Running autoconf..." ; autoconf || exit 1
+echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
+echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+
+if [ -z "$NOCONFIGURE" ]; then
+       ./configure "$@"
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..23813d4
--- /dev/null
@@ -0,0 +1,1514 @@
+# get rid of that stupid cache mechanism
+rm -f config.cache
+
+AC_INIT([ecore], [0.9.9.063], [enlightenment-devel@lists.sourceforge.net])
+release="ver-pre-svn-05"
+AC_PREREQ([2.52])
+AC_CONFIG_SRCDIR([configure.ac])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_ISC_POSIX
+
+AM_INIT_AUTOMAKE([1.6 dist-bzip2])
+AM_CONFIG_HEADER([config.h])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_GNU_SOURCE
+
+AC_LIBTOOL_WIN32_DLL
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL
+
+VMAJ=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $1);}'`
+VMIN=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $2);}'`
+VMIC=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $3);}'`
+SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'`
+version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
+AC_SUBST(version_info)
+
+AM_GNU_GETTEXT_VERSION([0.12.1])
+AM_GNU_GETTEXT([external])
+
+EFL_CHECK_PATH_MAX
+
+case "$host_os" in
+   mingw32ce* | cegcc*)
+      ;;
+   *)
+      ecore_config_release_info="-release $release"
+      ecore_con_release_info="-release $release"
+      ecore_directfb_release_info="-release $release"
+      ecore_evas_release_info="-release $release"
+      ecore_fb_release_info="-release $release"
+      ecore_file_release_info="-release $release"
+      ecore_imf_evas_release_info="-release $release"
+      ecore_imf_release_info="-release $release"
+      ecore_input_release_info="-release $release"
+      ecore_input_evas_release_info="-release $release"
+      ecore_ipc_release_info="-release $release"
+      ecore_cocoa_release_info="-release $release"
+      ecore_release_info="-release $release"
+      ecore_sdl_release_info="-release $release"
+      ecore_win32_release_info="-release $release"
+      ecore_x_release_info="-release $release"
+      ;;
+esac
+AC_SUBST(ecore_config_release_info)
+AC_SUBST(ecore_con_release_info)
+AC_SUBST(ecore_directfb_release_info)
+AC_SUBST(ecore_evas_release_info)
+AC_SUBST(ecore_fb_release_info)
+AC_SUBST(ecore_file_release_info)
+AC_SUBST(ecore_imf_evas_release_info)
+AC_SUBST(ecore_imf_release_info)
+AC_SUBST(ecore_input_release_info)
+AC_SUBST(ecore_input_evas_release_info)
+AC_SUBST(ecore_ipc_release_info)
+AC_SUBST(ecore_cocoa_release_info)
+AC_SUBST(ecore_release_info)
+AC_SUBST(ecore_sdl_release_info)
+AC_SUBST(ecore_win32_release_info)
+AC_SUBST(ecore_wince_release_info)
+AC_SUBST(ecore_x_release_info)
+
+
+with_max_log_level="<unset>"
+AC_ARG_WITH(internal-maximum-log-level,
+   [AC_HELP_STRING([--with-internal-maximum-log-level=NUMBER],
+                   [limit ecore internal log level to the given number, any call to EINA_LOG() with values greater than this will be compiled out, ignoring runtime settings, but saving function calls.])],
+   [
+    if test "x${withval}" != "xno"; then
+       if echo "${withval}" | grep '^[[0-9]]\+$' >/dev/null 2>/dev/null; then
+          AC_MSG_NOTICE([ignoring any EINA_LOG() with level greater than ${withval}])
+          AC_DEFINE_UNQUOTED(EINA_LOG_LEVEL_MAXIMUM, ${withval}, [if set, logging is limited to this amount.])
+          with_max_log_level="${withval}"
+       else
+          AC_MSG_ERROR([--with-internal-maximum-log-level takes a decimal number, got "${withval}" instead.])
+       fi
+    fi
+    ], [:])
+
+
+### Default options with respect to host
+
+# dependencies and options
+want_curl="no"
+want_abstract_sockets="no"
+want_gnutls="no"
+want_openssl="no"
+want_cares="no"
+want_cipher="no"
+want_signature="no"
+want_poll="yes"
+want_inotify="no"
+want_notify_win32="no"
+want_tslib="no"
+want_glib="no"
+
+# core modules
+want_ecore_con="yes"
+want_ecore_ipc="no"
+want_ecore_file="yes"
+want_ecore_config="no"
+want_ecore_imf="no"
+want_ecore_input="yes"
+
+# graphic system modules
+want_evas_simple_x11="no"
+want_ecore_x_xcb="no"
+want_ecore_x="no"
+want_ecore_win32="no"
+want_ecore_cocoa="no"
+want_ecore_sdl="no"
+want_ecore_fb="no"
+want_ecore_directfb="no"
+want_ecore_wince="no"
+
+# ecore_x options (both xlib and xcb)
+want_ecore_x_composite="yes"
+want_ecore_x_damage="yes"
+want_ecore_x_dpms="yes"
+want_ecore_x_randr="yes"
+want_ecore_x_render="yes"
+want_ecore_x_screensaver="yes"
+want_ecore_x_shape="yes"
+want_ecore_x_sync="yes"
+want_ecore_x_xfixes="yes"
+want_ecore_x_xinerama="yes"
+want_ecore_x_xprint="yes"
+want_ecore_x_xtest="yes"
+want_ecore_x_cursor="yes"
+want_ecore_x_input="yes"
+
+# ecore_evas modules
+want_ecore_evas="yes"
+want_ecore_evas_software_buffer="yes"
+want_ecore_evas_software_x11="no"
+want_ecore_evas_xrender_x11="no"
+want_ecore_evas_opengl_x11="no"
+want_ecore_evas_software_16_x11="no"
+want_ecore_evas_software_xcb="no"
+want_ecore_evas_xrender_xcb="no"
+want_ecore_evas_software_gdi="no"
+want_ecore_evas_software_ddraw="no"
+want_ecore_evas_direct3d="no"
+want_ecore_evas_opengl_glew="no"
+want_ecore_evas_software_16_ddraw="no"
+want_ecore_evas_cocoa="no"
+want_ecore_evas_software_sdl="no"
+want_ecore_evas_gl_sdl="no"
+want_ecore_evas_directfb="no"
+want_ecore_evas_fb="no"
+want_ecore_evas_software_16_wince="no"
+
+case "$host_os" in
+   mingw32ce* | cegcc*)
+      want_ecore_con="no"
+      want_ecore_wince="yes"
+      want_ecore_evas_software_16_wince="yes"
+      ;;
+   mingw*)
+      want_notify_win32="yes"
+      want_curl="yes"
+      want_glib="auto"
+      want_ecore_con="no"
+      want_ecore_imf="yes"
+      want_ecore_win32="yes"
+      want_ecore_evas_software_gdi="yes"
+      want_ecore_evas_software_ddraw="yes"
+      want_ecore_evas_direct3d="yes"
+      want_ecore_evas_opengl_glew="yes"
+      want_ecore_evas_software_16_ddraw="auto"
+      want_ecore_evas_software_sdl="yes"
+      want_ecore_evas_gl_sdl="yes"
+      ;;
+   darwin*)
+      want_curl="yes"
+      want_glib="auto"
+      want_gnutls="auto"
+      want_openssl="auto"
+      want_ecore_ipc="yes"
+      want_ecore_imf="yes"
+      want_ecore_cocoa="yes"
+      want_ecore_evas_cocoa="yes"
+      want_ecore_evas_software_sdl="yes"
+      want_ecore_evas_gl_sdl="yes"
+      ;;
+   *)
+      want_curl="yes"
+      want_glib="auto"
+      want_abstract_sockets="yes"
+      want_gnutls="auto"
+      want_openssl="auto"
+      want_cipher="yes"
+      want_signature="yes"
+      want_inotify="yes"
+      want_tslib="yes"
+      want_ecore_ipc="yes"
+      want_ecore_imf="yes"
+      want_ecore_x="yes"
+      want_ecore_evas_software_x11="yes"
+      want_ecore_evas_xrender_x11="yes"
+      want_ecore_evas_opengl_x11="yes"
+      want_ecore_evas_software_16_x11="yes"
+      want_ecore_evas_software_xcb="yes"
+      want_ecore_evas_xrender_xcb="yes"
+      want_ecore_evas_software_sdl="yes"
+      want_ecore_evas_gl_sdl="yes"
+      want_ecore_evas_directfb="yes"
+      want_ecore_evas_fb="yes"
+      ;;
+esac
+
+requirements_ecore=""
+requirements_ecore_con=""
+requirements_ecore_config=""
+requirements_ecore_directfb=""
+requirements_ecore_evas=""
+requirements_ecore_fb=""
+requirements_ecore_file=""
+requirements_ecore_imf=""
+requirements_ecore_imf_evas=""
+requirements_ecore_input=""
+requirements_ecore_input_evas=""
+requirements_ecore_ipc=""
+requirements_ecore_cocoa=""
+requirements_ecore_sdl=""
+requirements_ecore_x=""
+requirements_ecore_win32=""
+requirements_ecore_wince=""
+
+### Additional options to configure
+
+want_glib_integration_always=no
+AC_ARG_ENABLE(glib-integration-always,
+  AC_HELP_STRING([--enable-glib-integration-always], [enable glib integration when ecore_init() is called always]),
+  [want_glib_integration_always=$enableval])
+
+if test "x${want_glib_integration_always}" = "xyes" ; then
+  AC_DEFINE([GLIB_INTEGRATION_ALWAYS], [1], [Always integrate glib if support compiled])
+fi
+
+# abstract sockets (ecore_con.c)
+AC_ARG_ENABLE([abstract-sockets],
+   [AC_HELP_STRING([--disable-abstract-sockets], [disable abstract sockets.])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_abstract_sockets="yes"
+    else
+       want_abstract_sockets="no"
+    fi
+   ],
+   [want_abstract_sockets="yes"])
+
+if test "x${want_abstract_sockets}" = "xyes" ; then
+   AC_DEFINE([HAVE_ABSTRACT_SOCKETS], [1], [Have abstract sockets namespace])
+fi
+
+# Simple X11 build/link
+
+AC_ARG_ENABLE(simple-x11,
+  AC_HELP_STRING([--enable-simple-x11], [enable simple x11 linking]),
+  [want_evas_simple_x11=$enableval])
+
+# XIM
+AC_ARG_ENABLE([xim],
+   [AC_HELP_STRING([--disable-xim], [disable X Input Method.])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_xim="yes"
+    else
+       want_xim="no"
+    fi
+   ],
+   [want_xim="yes"])
+
+if test "x${want_xim}" = "xyes" ; then
+   AC_DEFINE([ENABLE_XIM], [1], [Enable X Input Method])
+fi
+
+# Unit tests
+
+EFL_CHECK_TESTS([enable_tests="yes"], [enable_tests="no"])
+
+
+### Checks for programs
+
+m4_ifdef([AC_PROG_OBJC],
+   [
+    AC_PROG_OBJC
+    _AM_DEPENDENCIES(OBJC)
+   ],
+   [
+    AC_CHECK_TOOL([OBJC], [gcc])
+    AC_SUBST([OBJC])
+    AC_SUBST([OBJCFLAGS])
+   ])
+m4_ifndef([am__fastdepOBJC], [
+    AM_CONDITIONAL([am__fastdepOBJC], [false])
+    AC_SUBST([cocoa_ldflags])
+])
+
+AC_PROG_CXX
+AC_PROG_CC
+
+have_gnu_objc=${ac_cv_objc_compiler_gnu}
+
+# doxygen program for documentation building
+
+EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"])
+
+# The first call to PKG_CHECK_MODULES is done conditionally,
+# so we should include this here:
+PKG_PROG_PKG_CONFIG
+
+# Check whether pkg-config supports Requires.private
+if $PKG_CONFIG --atleast-pkgconfig-version 0.22; then
+   pkgconfig_requires_private="Requires.private"
+else
+   pkgconfig_requires_private="Requires"
+fi
+AC_SUBST(pkgconfig_requires_private)
+
+
+### Checks for libraries
+
+# Evil library for compilation on Windows
+
+case "$host_os" in
+   mingw* | cegcc*)
+      PKG_CHECK_MODULES([EVIL], [evil])
+      AC_DEFINE(HAVE_EVIL, 1, [Set to 1 if Evil library is installed])
+      requirements_ecore="evil ${requirements_ecore}"
+      requirements_ecore_evas="evil ${requirements_ecore_evas}"
+      requirements_ecore_file="evil ${requirements_ecore_file}"
+      requirements_ecore_imf="evil ${requirements_ecore_imf}"
+      requirements_ecore_imf_evas="evil ${requirements_ecore_imf_evas}"
+      EFL_ECORE_BUILD="-DEFL_ECORE_BUILD"
+      EFL_ECORE_FILE_BUILD="-DEFL_ECORE_FILE_BUILD"
+      EFL_ECORE_EVAS_BUILD="-DEFL_ECORE_EVAS_BUILD"
+      EFL_ECORE_IMF_BUILD="-DEFL_ECORE_IMF_BUILD"
+      EFL_ECORE_INPUT_BUILD="-DEFL_ECORE_INPUT_BUILD"
+      EFL_ECORE_INPUT_EVAS_BUILD="-DEFL_ECORE_INPUT_EVAS_BUILD"
+      ;;
+esac
+
+have_win32=""
+have_wince=""
+case "$host_os" in
+   mingw32ce* | cegcc*)
+      EFL_ECORE_WINCE_BUILD="-DEFL_ECORE_WINCE_BUILD"
+      requirements_ecore_wince="evil ${requirements_ecore_wince}"
+      have_wince="yes"
+      ;;
+   mingw*)
+      EFL_ECORE_WIN32_BUILD="-DEFL_ECORE_WIN32_BUILD"
+      EFL_ECORE_SDL_BUILD="-DEFL_ECORE_SDL_BUILD"
+      requirements_ecore_win32="evil ${requirements_ecore_win32}"
+      requirements_ecore_sdl="evil ${requirements_ecore_sdl}"
+      have_win32="yes"
+      ;;
+esac
+
+AC_SUBST(EFL_ECORE_BUILD)
+AC_SUBST(EFL_ECORE_FILE_BUILD)
+AC_SUBST(EFL_ECORE_EVAS_BUILD)
+AC_SUBST(EFL_ECORE_IMF_BUILD)
+AC_SUBST(EFL_ECORE_INPUT_BUILD)
+AC_SUBST(EFL_ECORE_INPUT_EVAS_BUILD)
+AC_SUBST(EFL_ECORE_WINCE_BUILD)
+AC_SUBST(EFL_ECORE_WIN32_BUILD)
+AC_SUBST(EFL_ECORE_SDL_BUILD)
+
+AM_CONDITIONAL(ECORE_HAVE_WINCE, test "x${have_wince}" = "xyes")
+AM_CONDITIONAL(ECORE_HAVE_WIN32, test "x${have_win32}" = "xyes")
+
+WIN32_LIBS=""
+case "$host_os" in
+   mingw32ce* | cegcc*)
+      WIN32_LIBS="-lws2"
+      dlopen_libs="-ldl"
+      ;;
+   mingw*)
+      WIN32_LIBS="-lws2_32"
+      dlopen_libs="-ldl"
+      ;;
+   *)
+      AC_CHECK_LIB(dl, dlopen, dlopen_libs=-ldl)
+      ;;
+esac
+AC_SUBST(WIN32_LIBS)
+AC_SUBST(dlopen_libs)
+
+# Eina library
+
+PKG_CHECK_MODULES(EINA, [eina-0])
+#FIXME check all the requirements when the eina move will be finished
+requirements_ecore="eina-0 ${requirements_ecore}"
+requirements_ecore_con="ecore eina-0 ${requirements_ecore_con}"
+requirements_ecore_config="ecore eina-0 ${requirements_ecore_config}"
+requirements_ecore_directfb="ecore eina-0 ${requirements_ecore_directfb}"
+requirements_ecore_evas="ecore eina-0 ${requirements_ecore_evas}"
+requirements_ecore_fb="ecore eina-0 ${requirements_ecore_fb}"
+requirements_ecore_file="ecore eina-0 ${requirements_ecore_file}"
+requirements_ecore_imf="ecore eina-0 ${requirements_ecore_imf}"
+requirements_ecore_imf_evas="ecore eina-0 ${requirements_ecore_imf_evas}"
+requirements_ecore_input="ecore eina-0 ${requirements_ecore_input}"
+requirements_ecore_input_evas="ecore eina-0 ${requirements_ecore_input_evas}"
+requirements_ecore_ipc="ecore eina-0 ${requirements_ecore_ipc}"
+requirements_ecore_cocoa="ecore eina-0 ${requirements_ecore_cocoa}"
+requirements_ecore_sdl="ecore eina-0 ${requirements_ecore_sdl}"
+requirements_ecore_win32="ecore eina-0 ${requirements_ecore_win32}"
+requirements_ecore_wince="ecore eina-0 ${requirements_ecore_wince}"
+requirements_ecore_x="ecore eina-0 ${requirements_ecore_x}"
+
+
+# glib support (main loop integration)
+AC_ARG_ENABLE([glib],
+   [AC_HELP_STRING([--disable-glib], [disable glib support. @<:@default=detect@:>@])],
+   [want_glib=$enableval], [])
+
+if test "x$want_glib" != "xno"; then
+   PKG_CHECK_MODULES([GLIB], [glib-2.0], [have_glib="yes"], [have_glib="no"])
+else
+   have_glib="no"
+fi
+if test "x$want_glib" = "xyes" -a "x$have_glib" = "xno"; then
+   AC_MSG_ERROR([GLib support requested, but no GLib found by pkg-config.])
+elif test "x$have_glib" = "xyes"; then
+   AC_DEFINE(HAVE_GLIB, [1], [Have GLib])
+   requirements_ecore="glib-2.0 ${requirements_ecore}"
+fi
+
+
+# SDL library (ecore_sdl)
+
+have_sdl="no"
+SDL_CONFIG="sdl-config"
+AC_ARG_WITH([sdl-config],
+   [AC_HELP_STRING([--with-sdl-config=PATH], [use sdl-config specified])],
+   [
+    SDL_CONFIG=$withval
+    AC_MSG_NOTICE([using ${SDL_CONFIG} for sdl-config])
+   ])
+
+AC_PATH_PROG([SDL_CONFIG], ["sdl-config"], [""], [$PATH])
+
+if test -n "$SDL_CONFIG" ; then
+   SDL_CFLAGS=`$SDL_CONFIG --cflags`
+   SDL_LIBS=`$SDL_CONFIG --libs`
+   AC_SUBST(SDL_CFLAGS)
+   AC_SUBST(SDL_LIBS)
+   have_sdl="yes"
+else
+   PKG_CHECK_MODULES([SDL], [sdl >= 1.2.0], [have_sdl="yes"], [have_sdl="no"])
+fi
+
+if test "x${have_sdl}" = "xyes" ; then
+   PKG_CHECK_EXISTS([sdl >= 1.3.0],
+      [AC_DEFINE(BUILD_ECORE_EVAS_SDL_130, 1, [Support for SVN SDL])])
+fi
+
+
+# DirectFB library (ecore_directfb)
+
+PKG_CHECK_MODULES([DIRECTFB],
+   [directfb >= 0.9.16],
+   [have_directfb="yes"],
+   [have_directfb="no"])
+
+
+# Eet library (ecore_config)
+
+PKG_CHECK_MODULES([EET],
+   [eet >= 1.0.0],
+   [have_eet="yes"],
+   [have_eet="no"])
+
+
+# Xlib and XCB (ecore_x)
+
+have_x="no"
+have_ecore_x="no"
+have_ecore_x_xlib="no"
+have_ecore_x_xcb="no"
+
+x_dir="";
+x_includes="";
+x_cflags="";
+x_libs="";
+
+ecore_x_libs_private=""
+
+AC_ARG_ENABLE(ecore-x-composite,
+   [AC_HELP_STRING([--disable-ecore-x-composite],
+       [disable the ecore_x support for Xcomposite extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_composite=$enableval])
+
+AC_ARG_ENABLE(ecore-x-damage,
+   [AC_HELP_STRING([--disable-ecore-x-damage],
+       [disable the ecore_x support for Xdamage extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_damage=$enableval])
+
+AC_ARG_ENABLE(ecore-x-dpms,
+   [AC_HELP_STRING([--disable-ecore-x-dpms],
+       [disable the ecore_x support for Xdpms extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_dpms=$enableval])
+
+AC_ARG_ENABLE(ecore-x-randr,
+   [AC_HELP_STRING([--disable-ecore-x-randr],
+       [disable the ecore_x support for Xrandr extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_randr=$enableval])
+
+AC_ARG_ENABLE(ecore-x-render,
+   [AC_HELP_STRING([--disable-ecore-x-render],
+       [disable the ecore_x support for Xrender extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_render=$enableval])
+
+AC_ARG_ENABLE(ecore-x-screensaver,
+   [AC_HELP_STRING([--disable-ecore-x-screensaver],
+       [disable the ecore_x support for Xscreensaver extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_screensaver=$enableval])
+
+AC_ARG_ENABLE(ecore-x-shape,
+   [AC_HELP_STRING([--disable-ecore-x-shape],
+       [disable the ecore_x support for Xshape extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_shape=$enableval])
+
+AC_ARG_ENABLE(ecore-x-sync,
+   [AC_HELP_STRING([--disable-ecore-x-sync],
+       [disable the ecore_x support for Xsync extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_sync=$enableval])
+
+AC_ARG_ENABLE(ecore-x-xfixes,
+   [AC_HELP_STRING([--disable-ecore-x-xfixes],
+       [disable the ecore_x support for Xfixes extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_xfixes=$enableval])
+
+AC_ARG_ENABLE(ecore-x-xinerama,
+   [AC_HELP_STRING([--disable-ecore-x-xinerama],
+       [disable the ecore_x support for Xinerama extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_xinerama=$enableval])
+
+AC_ARG_ENABLE(ecore-x-xprint,
+   [AC_HELP_STRING([--disable-ecore-x-xprint],
+       [disable the ecore_x support for Xprint extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_xprint=$enableval])
+
+AC_ARG_ENABLE(ecore-x-xtest,
+   [AC_HELP_STRING([--disable-ecore-x-xtest],
+       [disable the ecore_x support for Xtest extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_xtest=$enableval])
+
+AC_ARG_ENABLE(ecore-x-cursor,
+   [AC_HELP_STRING([--disable-ecore-x-cursor],
+       [disable the ecore_x support for Xcursor extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_cursor=$enableval])
+
+AC_ARG_ENABLE(ecore-x-input,
+   [AC_HELP_STRING([--disable-ecore-x-input],
+       [disable the ecore_x support for Xinput/Xinput2 extension.
+        @<:@default=detect@:>@])],
+   [want_ecore_x_input=$enableval])
+
+
+AC_ARG_ENABLE(ecore-x-xcb,
+   [AC_HELP_STRING([--enable-ecore-x-xcb],
+       [enable the ecore_x module with XCB backend. @<:@default=disabled@:>@])],
+   [want_ecore_x_xcb=$enableval],
+   [want_ecore_x_xcb="no"])
+
+AC_MSG_CHECKING(whether ecore_x with XCB backend is to be built)
+AC_MSG_RESULT($want_ecore_x_xcb)
+
+if test "x$want_ecore_x_xcb" = "xyes" ; then
+  PKG_CHECK_MODULES(XCB, xcb xcb-icccm xcb-image xcb-keysyms pixman-1,
+    [ have_ecore_x_xcb="yes"
+      requirements_ecore_x="xcb xcb-icccm xcb-image xcb-keysyms pixman-1 ${requirements_ecore_x}" ],
+    [ have_ecore_x_xcb="no" ])
+
+  if test "x$have_ecore_x_xcb" = "xyes" ; then
+    if test "x$want_ecore_x_composite" != "xno"; then
+      PKG_CHECK_MODULES(XCB_COMPOSITE, xcb-composite,
+        [ have_ecore_x_xcb_composite="yes"
+          requirements_ecore_x="xcb-composite ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_COMPOSITE, 1, [Build support for XCB composite]) ],
+        [ have_ecore_x_xcb_composite="no" ])
+    else
+      have_ecore_x_xcb_composite="no"
+      AC_MSG_NOTICE("composite extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_damage" != "xno"; then
+      PKG_CHECK_MODULES(XCB_DAMAGE, xcb-damage,
+        [ have_ecore_x_xcb_damage="yes"
+          requirements_ecore_x="xcb-damage ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_DAMAGE, 1, [Build support for XCB damage]) ],
+        [ have_ecore_x_xcb_damage="no" ])
+    else
+      have_ecore_x_xcb_damage="no"
+      AC_MSG_NOTICE("damage extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_dpms" != "xno"; then
+      PKG_CHECK_MODULES(XCB_DPMS, xcb-dpms,
+        [ have_ecore_x_xcb_dpms="yes"
+          requirements_ecore_x="xcb-dpms ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_DPMS, 1, [Build support for XCB dpms]) ],
+        [ have_ecore_x_xcb_dpms="no" ])
+    else
+      have_ecore_x_xcb_dpms="no"
+      AC_MSG_NOTICE("dpms extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_randr" != "xno"; then
+      PKG_CHECK_MODULES(XCB_RANDR, xcb-randr,
+        [ have_ecore_x_xcb_randr="yes"
+          requirements_ecore_x="xcb-randr ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_RANDR, 1, [Build support for XCB randr]) ],
+        [ have_ecore_x_xcb_randr="no" ])
+    else
+      have_ecore_x_xcb_randr="no"
+      AC_MSG_NOTICE("randr extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_render" != "xno"; then
+      PKG_CHECK_MODULES(XCB_RENDER, xcb-render,
+        [ have_ecore_x_xcb_render="yes"
+          requirements_ecore_x="xcb-render ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_RENDER, 1, [Build support for XCB render]) ],
+        [ have_ecore_x_xcb_render="no" ])
+    else
+      have_ecore_x_xcb_render="no"
+      AC_MSG_NOTICE("render extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_screensaver" != "xno"; then
+      PKG_CHECK_MODULES(XCB_SCREENSAVER, xcb-screensaver,
+        [ have_ecore_x_xcb_screensaver="yes"
+          requirements_ecore_x="xcb-screensaver ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_SCREENSAVER, 1, [Build support for XCB screensaver]) ],
+        [ have_ecore_x_xcb_screensaver="no" ])
+    else
+      have_ecore_x_xcb_screensaver="no"
+      AC_MSG_NOTICE("screensaver extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_shape" != "xno"; then
+      PKG_CHECK_MODULES(XCB_SHAPE, xcb-shape,
+        [ have_ecore_x_xcb_shape="yes"
+          requirements_ecore_x="xcb-shape ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_SHAPE, 1, [Build support for XCB shape]) ],
+        [ have_ecore_x_xcb_shape="no" ])
+    else
+      have_ecore_x_xcb_shape="no"
+      AC_MSG_NOTICE("shape extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_sync" != "xno"; then
+      PKG_CHECK_MODULES(XCB_SYNC, xcb-sync,
+        [ have_ecore_x_xcb_sync="yes"
+          requirements_ecore_x="xcb-sync ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_SYNC, 1, [Build support for XCB sync]) ],
+        [ have_ecore_x_xcb_sync="no" ])
+    else
+      have_ecore_x_xcb_sync="no"
+      AC_MSG_NOTICE("sync extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_xfixes" != "xno"; then
+      PKG_CHECK_MODULES(XCB_XFIXES, xcb-xfixes,
+        [ have_ecore_x_xcb_xfixes="yes"
+          requirements_ecore_x="xcb-xfixes ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_FIXES, 1, [Build support for XCB xfixes]) ],
+        [ have_ecore_x_xcb_xfixes="no" ])
+    else
+      have_ecore_x_xcb_xfixes="no"
+      AC_MSG_NOTICE("xfixes extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_xinerama" != "xno"; then
+      PKG_CHECK_MODULES(XCB_XINERAMA, xcb-xinerama,
+        [ have_ecore_x_xcb_xinerama="yes"
+          requirements_ecore_x="xcb-xinerama ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_XINERAMA, 1, [Build support for XCB xinerama]) ],
+        [ have_ecore_x_xcb_xinerama="no" ])
+    else
+      have_ecore_x_xcb_xinerama="no"
+      AC_MSG_NOTICE("xinerama extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_xprint" != "xno"; then
+      PKG_CHECK_MODULES(XCB_XPRINT, xcb-xprint,
+        [ have_ecore_x_xcb_xprint="yes"
+          requirements_ecore_x="xcb-xprint ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_XPRINT, 1, [Build support for XCB xprint]) ],
+        [ have_ecore_x_xcb_xprint="no" ])
+    else
+      have_ecore_x_xcb_xprint="no"
+      AC_MSG_NOTICE("xprint extension explicitly disabled")
+    fi
+
+    if test "x$want_ecore_x_xtest" != "xno"; then
+      PKG_CHECK_MODULES(XCB_XTEST, xcb-xtest,
+        [ have_ecore_x_xcb_xtest="yes"
+          requirements_ecore_x="xcb-xtest ${requirements_ecore_x}"
+          AC_DEFINE(ECORE_XCB_XTEST, 1, [Build support for XCB xtest]) ],
+        [ have_ecore_x_xcb_xtest="no" ])
+    else
+      have_ecore_x_xcb_xtest="no"
+      AC_MSG_NOTICE("xtest extension explicitly disabled")
+    fi
+
+    AC_DEFINE(HAVE_ECORE_X_XCB, 1, [Defined to 1 if XCB is enabled.])
+
+    x_cflags=$XCB_CFLAGS
+    x_libs=$XCB_LIBS
+    have_x="yes"
+
+    have_ecore_x_xcb_define="-DHAVE_ECORE_X_XCB"
+    AC_SUBST(have_ecore_x_xcb_define)
+  fi
+fi
+
+if ! test "x$have_ecore_x_xcb" = "xyes" ; then
+  AC_PATH_XTRA
+  AC_CHECK_HEADER(X11/X.h,
+    [
+     if test "x$want_evas_simple_x11" = "xyes"; then
+       x_libs="${x_libs} -lX11 -lXext"
+     else
+       x_dir=${x_dir:-/usr/X11R6}
+       x_cflags=${x_cflags:--I${x_includes:-$x_dir/include}}
+       x_libs="${x_libs:--L${x_libraries:-$x_dir/lib}} -lX11 -lXext"
+     fi
+     have_ecore_x_xlib="yes"
+    ]
+  )
+
+  if test "x$have_ecore_x_xlib" = "xyes"; then
+    Xcursor_libs=""
+    Xcursor_cflags=""
+    use_Xcursor="no"
+    PCFLAGS=$CFLAGS
+    CFLAGS="$x_cflags $x_includes"
+
+    if test "x$want_ecore_x_cursor" = "xyes"; then
+      AC_CHECK_HEADER(X11/Xcursor/Xcursor.h,
+        [
+          AC_CHECK_LIB(Xcursor, XcursorImageLoadCursor,
+            [
+              AC_DEFINE(ECORE_XCURSOR, 1, [Build support for Xcursor])
+              Xcursor_cflags=""
+              Xcursor_libs="-lXcursor"
+              use_Xcursor="yes"
+            ], [
+              Xcursor_cflags=""
+              Xcursor_libs=""
+              use_Xcursor="no"
+            ], [
+              $x_libs -lXrender
+            ]
+          )
+        ], [
+          Xcursor_cflags=""
+          Xcursor_libs=""
+          use_Xcursor="no"
+        ], [
+          #include <X11/Xlib.h>
+        ]
+      )
+      CFLAGS=$PCFLAGS
+    else
+      Xcursor_cflags=""
+      Xcursor_libs=""
+      use_Xcursor="no"
+      AC_MSG_NOTICE("Xcursor explicitly disabled")
+    fi
+
+    AC_SUBST(Xcursor_cflags)
+    AC_SUBST(Xcursor_libs)
+
+    ECORE_CHECK_X_EXTENSION([Xkb], [XKB.h], [X11], [XkbSetDetectableAutoRepeat], [$want_ecore_x_xkb])
+    ECORE_CHECK_X_EXTENSION([Xcomposite], [Xcomposite.h], [Xcomposite], [XCompositeQueryExtension], [$want_ecore_x_composite])
+    ECORE_CHECK_X_EXTENSION([Xdamage], [Xdamage.h], [Xdamage], [XDamageSubtract], [$want_ecore_x_damage])
+    ECORE_CHECK_X_EXTENSION([Xdpms], [dpms.h], [Xdpms], [DPMSQueryExtension], [$want_ecore_x_dpms])
+    if test "x$use_xdpms" = "xno" ; then
+      ECORE_CHECK_X_EXTENSION([Xdpms], [dpms.h], [Xext], [DPMSQueryExtension], [$want_ecore_x_dpms])
+    fi
+    ECORE_CHECK_X_EXTENSION([Xfixes], [Xfixes.h], [Xfixes], [XFixesExpandRegion], [$want_ecore_x_xfixes])
+    ECORE_CHECK_X_EXTENSION([Xinerama], [Xinerama.h], [Xinerama], [XineramaQueryScreens], [$want_ecore_x_xinerama])
+    ECORE_CHECK_X_EXTENSION([Xprint], [Print.h], [Xp], [XpQueryScreens], [$want_ecore_x_xprint])
+    ECORE_CHECK_X_EXTENSION([Xrandr], [Xrandr.h], [Xrandr], [XRRGetScreenResourcesCurrent], [$want_ecore_x_randr])
+    ECORE_CHECK_X_EXTENSION([Xrender], [Xrender.h], [Xrender], [XRenderFindVisualFormat], [$want_ecore_x_render])
+    ECORE_CHECK_X_EXTENSION([Xtest], [XTest.h], [Xtst], [XTestFakeKeyEvent], [$want_ecore_x_xtest])
+    ECORE_CHECK_X_EXTENSION([Xss], [scrnsaver.h], [Xss], [XScreenSaverSelectInput], [$want_ecore_x_screensaver])
+    ECORE_CHECK_X_EXTENSION([Xi2], [XInput2.h], [Xi], [XIQueryDevice], [$want_ecore_x_input])
+
+    ecore_x_libs_private="${Xcursor_libs} ${XKB_LIBS} ${XCOMPOSITE_LIBS} ${XDAMAGE_LIBS} ${XDPMS_LIBS} ${XFIXES_LIBS} ${XINERAMA_LIBS} ${XPRINT_LIBS} ${XRANDR_LIBS} ${XRENDER_LIBS} ${XTEST_LIBS} ${XSS_LIBS} ${XI2_LIBS}"
+
+    AC_DEFINE(HAVE_ECORE_X_XLIB, 1, [Defined to 1 if Xlib is enabled.])
+    have_x="yes"
+
+    have_ecore_x_xlib="yes"
+  fi
+fi
+
+AC_SUBST(x_cflags)
+AC_SUBST(x_includes)
+AC_SUBST(x_libs)
+AC_SUBST(ecore_x_libs_private)
+
+AM_CONDITIONAL(BUILD_ECORE_X_XLIB, test $have_ecore_x_xlib = yes)
+AM_CONDITIONAL(BUILD_ECORE_X_XCB, test $have_ecore_x_xcb = yes)
+
+
+# Evas library (ecore_config, ecore_input_evas, ecore_imf_evas and ecore_evas)
+
+PKG_CHECK_MODULES([EVAS], [evas >= 0.9.9],
+   [have_evas="yes"],
+   [have_evas="no"])
+
+
+### Checks for header files
+
+AC_HEADER_SYS_WAIT
+
+have_addrinfo="no"
+case "$host_os" in
+   mingw* | cegcc*)
+      AC_DEFINE(HAVE_DLFCN_H, 1, [Define to 1 if you have the <dlfcn.h> header file.])
+      AC_DEFINE(HAVE_SYS_MMAN_H, 1, [Define to 1 if you have the <sys/mman.h> header file.])
+      AC_DEFINE(HAVE_SYS_TIME_H, 1, [Define to 1 if you have the <sys/time.h> header file.])
+      have_addrinfo="yes"
+      ;;
+   *)
+      AC_CHECK_HEADERS([dlfcn.h features.h langinfo.h locale.h sys/time.h sys/mman.h signal.h sys/resource.h])
+      ;;
+esac
+
+# ecore_con
+
+AC_CHECK_HEADERS([arpa/inet.h arpa/nameser.h netinet/tcp.h netinet/in.h sys/socket.h sys/un.h ws2tcpip.h netdb.h])
+
+if test "x${ac_cv_header_netdb_h}" = "xyes" ; then
+   have_addrinfo="yes"
+fi
+
+# Framebuffer (ecore_fb)
+have_fb="no"
+AC_CHECK_HEADER([linux/fb.h],
+   [AC_CHECK_HEADER([linux/input.h], [have_fb="yes"])])
+
+# Cocoa header files (ecore_cocoa)
+
+cocoa_ldflags="";
+have_cocoa="no"
+m4_ifdef([AC_PROG_OBJC], [
+    if test "x${have_gnu_objc}" = "xyes" ; then
+       AC_LANG_PUSH([Objective C])
+       AC_CHECK_HEADER([Cocoa/Cocoa.h],
+          [
+           have_cocoa="yes"
+           cocoa_ldflags="-framework Cocoa"
+          ])
+       AC_LANG_POP([Objective C])
+    fi
+])
+AC_SUBST(cocoa_ldflags)
+
+# basic pthread support
+
+EFL_CHECK_PTHREAD([no], [have_pthread="yes"], [have_pthread="no"])
+
+### Checks for types
+AC_CHECK_SIZEOF(int, 4)
+AC_CHECK_SIZEOF(long, 4)
+
+
+### Checks for structures
+
+
+### Checks for compiler characteristics
+AM_PROG_CC_STDC
+AC_C_CONST
+AC_C_BIGENDIAN
+AC_HEADER_STDC
+AC_C___ATTRIBUTE__
+
+WIN32_CPPFLAGS=""
+WIN32_CFLAGS=""
+case "$host_os" in
+   mingw32ce*)
+      WIN32_CPPFLAGS="-D_WIN32_WCE=0x0420"
+      ;;
+   cegcc*)
+      WIN32_CPPFLAGS="-D_WIN32_WCE=0x0420"
+      WIN32_CFLAGS="-mwin32"
+      ;;
+   mingw*)
+      WIN32_CPPFLAGS="-D_WIN32_WINNT=0x0501"
+      ;;
+esac
+AC_SUBST(WIN32_CPPFLAGS)
+AC_SUBST(WIN32_CFLAGS)
+
+
+### Checks for linker characteristics
+
+# use --enable-auto-import on Windows
+
+lt_enable_auto_import=""
+case "$host_os" in
+   mingw* | cegcc*)
+      lt_enable_auto_import="-Wl,--enable-auto-import"
+      ;;
+esac
+AC_SUBST(lt_enable_auto_import)
+
+### Checks for library functions
+AC_FUNC_ALLOCA
+AC_CHECK_FUNCS(gettimeofday strlcpy)
+
+have_atfile_source=auto
+AC_ARG_ENABLE(atfile-source,
+        AC_HELP_STRING([--disable-atfile-source],
+                       [disable use of atfile source functions as openat and mkdirat @<:@default=detect@:>@]),
+        [have_atfile_source=$enableval], [have_atfile_source=auto])
+
+if test "x$have_atfile_source" != "xno"; then
+        AC_CHECK_FUNCS(mkdirat,
+                [
+                have_atfile_source=yes
+                AC_DEFINE(HAVE_ATFILE_SOURCE, 1, [mkdirat exists])
+                ],
+                [
+                if test "x$have_atfile_source" = "xyes"; then
+                        AC_MSG_ERROR([required atfile-source but no mkdirat()])
+                fi
+                have_atfile_source=no
+                ])
+fi
+
+### Checks for optionnal feature
+AC_CHECK_FUNC(mallinfo,
+       [
+         have_mallinfo=yes
+         AC_DEFINE(HAVE_MALLINFO, 1, [Gather memory statistic])
+       ], [
+         have_mallinfo=no
+       ])
+
+### Ecore modules
+
+## Core modules
+
+# ecore_con
+ECORE_CHECK_MODULE([con], [${want_ecore_con}], [Con], [${have_addrinfo}])
+
+have_curl="no"
+have_gnutls="no"
+have_openssl="no"
+have_cares="no"
+if test "x${have_ecore_con}" = "xyes" ; then
+
+   ECORE_CHECK_CURL([${want_curl}],
+      [
+       have_curl="yes"
+       requirements_ecore_con="libcurl ${requirements_ecore_con}"
+      ],
+      [have_curl="no"])
+
+   ECORE_CHECK_GNUTLS([${want_gnutls}],
+      [have_gnutls="yes"],
+      [have_gnutls="no"])
+
+   ECORE_CHECK_OPENSSL([${want_openssl}],
+      [have_openssl="yes"],
+      [have_openssl="no"])
+
+   if test "x${have_gnutls}" = "xyes" ; then
+      requirements_ecore_con="gnutls ${requirements_ecore_con}"
+      # no need to add it to req_ecore_ipc, since they
+      # depends on ecore_con anyway.
+   else
+      if test "x${have_openssl}" = "xyes" ; then
+         requirements_ecore_con="openssl ${requirements_ecore_con}"
+         # no need to add it to req_ecore_ipc, since they
+         # depends on ecore_con anyway.
+      fi
+   fi
+
+   ECORE_CHECK_CARES([${want_cares}],
+      [
+       have_cares="yes"
+       requirements_ecore_con="libcares ${requirements_ecore_con}"
+      ],
+      [have_cares="no"])
+
+fi
+
+AM_CONDITIONAL([HAVE_CARES], [test "x${have_cares}" = "xyes"])
+
+# ecore_ipc
+ECORE_CHECK_MODULE([ipc], [${want_ecore_ipc}], [Ipc], [${have_ecore_con}],
+   [requirements_ecore_ipc="ecore-con ${requirements_ecore_ipc}"])
+
+# ecore_file
+ECORE_CHECK_MODULE([file], [${want_ecore_file}], [File])
+
+have_poll="no"
+have_inotify="no"
+have_notify_win32="no"
+if test "x${have_ecore_file}" = "xyes" ; then
+   ECORE_CHECK_POLL([${want_poll}], [have_poll="yes"], [have_poll="no"])
+   ECORE_CHECK_INOTIFY([${want_inotify}], [have_inotify="yes"], [have_inotify="no"])
+   ECORE_CHECK_NOTIFY_WIN32([${want_notify_win32}], [have_notify_win32="yes"], [have_notify_win32="no"])
+
+   if test "x${have_ecore_con}" = "xyes" ; then
+      requirements_ecore_file="ecore-con ${requirements_ecore_file}"
+   fi
+fi
+
+# ecore_config
+ecore_config_deps="no"
+if test "x${have_eet}" = "xyes" -a "x${have_evas}"  -a "x${have_ecore_ipc}" ; then
+   ecore_config_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([config], [${want_ecore_config}], [Config], [${ecore_config_deps}],
+   [requirements_ecore_config="ecore-ipc evas eet ${requirements_ecore_config}"])
+
+# ecore_imf
+
+ECORE_CHECK_MODULE([imf], [${want_ecore_imf}], [Imf])
+
+# ecore_imf_evas
+
+ecore_imf_evas_deps="no"
+if test "x${have_ecore_imf}" = "xyes" -a "x${have_evas}" = "xyes" ; then
+   ecore_imf_evas_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([imf-evas], [${want_ecore_imf}], [Imf_Evas], [${ecore_imf_evas_deps}],
+   [requirements_ecore_imf_evas="ecore-imf evas ${requirements_ecore_imf_evas}"])
+
+# ecore_input{_evas}
+ECORE_CHECK_MODULE([input], [${want_ecore_input}], [Input])
+ECORE_CHECK_MODULE([input-evas], [${want_ecore_input}], [Input_Evas], [${have_evas}],
+   [requirements_ecore_input_evas="ecore-input evas ${requirements_ecore_input}"])
+
+## Graphic systems
+
+# ecore_x{cb}
+
+ecore_x_deps="no"
+if test "x${have_x}" = "xyes" -a \
+        "x${have_ecore_input}" = "xyes" ; then
+   ecore_x_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([x], [${want_ecore_x}], [X], [${ecore_x_deps}],
+  [
+   ecore_x_libs="$ecore_x_libs $x_libs"
+   requirements_ecore_x="ecore-input ${requirements_ecore_x}"
+  ])
+
+# ecore_win32
+
+ECORE_CHECK_MODULE([win32], [${want_ecore_win32}], [Win32], [${have_ecore_input}],
+   [
+    ecore_win32_libs="-lole32 -lgdi32"
+    requirements_ecore_win32="ecore-input ${requirements_ecore_win32}"
+   ])
+AC_SUBST(ecore_win32_libs)
+
+# ecore_cocoa
+
+ecore_cocoa_deps="no"
+if test "x${have_ecore_input}" = "xyes" -a "x${have_cocoa}" = "xyes" ; then
+   ecore_cocoa_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([cocoa], [${want_ecore_cocoa}], [Cocoa], [${ecore_cocoa_deps}],
+   [requirements_ecore_cocoa="ecore-input ${requirements_ecore_cocoa}"])
+
+# ecore_sdl
+
+ecore_sdl_deps="no"
+if test "x${have_sdl}" = "xyes" -a "x${have_ecore_input}" = "xyes" ; then
+   ecore_sdl_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([sdl], [${want_ecore_sdl}], [Sdl], [${ecore_sdl_deps}],
+   [requirements_ecore_sdl="ecore-input ${requirements_ecore_sdl}"])
+
+# ecore_fb
+ECORE_CHECK_MODULE([fb], [${want_ecore_fb}], [FB], [$have_fb])
+
+if test "x${have_ecore_fb}" = "xyes" ; then
+   ECORE_CHECK_TSLIB([${want_tslib}],
+      [
+       have_tslib="yes"
+       requirements_ecore_fb="${_tslib_requirement} ${requirements_ecore_fb}"
+      ],
+      [have_tslib="no"])
+fi
+
+# ecore_directfb
+
+ECORE_CHECK_MODULE([directfb], [${want_ecore_directfb}], [DirectFB], [${have_directfb}],
+   [requirements_ecore_directfb="directfb ${requirements_ecore_directfb}"])
+
+# ecore_wince
+
+ECORE_CHECK_MODULE([wince], [${want_ecore_wince}], [WinCE], [${have_ecore_input}],
+   [requirements_ecore_win32="ecore-input ${requirements_ecore_win32}"])
+
+## Ecore Evas
+
+# ecore_evas
+
+ecore_evas_deps="no"
+if test "x${have_evas}" = "xyes" -a "x${have_ecore_input}" = "xyes" -a "x${have_ecore_input_evas}" = "xyes" ; then
+   ecore_evas_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([evas], [${want_ecore_evas}], [Evas], [${ecore_evas_deps}],
+  [requirements_ecore_evas="ecore-input ecore-input-evas evas ${requirements_ecore_evas}"])
+
+# ecore_evas_buffer
+
+ECORE_EVAS_CHECK_MODULE([software-buffer],
+   [${want_ecore_evas_software_buffer}],
+   [Software Buffer],
+   [yes])
+
+# ecore_evas_x11
+
+# ecore_evas_software_x11
+
+ECORE_EVAS_CHECK_MODULE([software-x11],
+   [${want_ecore_evas_software_x11}],
+   [Software X11],
+   [${have_ecore_x}])
+
+have_ecore_evas_software_xlib=no"
+have_ecore_evas_software_xcb=no"
+if test "x$have_ecore_evas_software_x11" = "xyes" ; then
+   have_ecore_evas_software_xlib=`${PKG_CONFIG} --variable=Xlib evas-software-x11`
+   if test "x${have_ecore_evas_software_xlib}" = "xyes" -a "x${have_ecore_x_xlib}" = "xyes" ; then
+      AC_DEFINE(BUILD_ECORE_EVAS_SOFTWARE_XLIB, 1, [Evas Software Xlib Engine Support])
+   fi
+   have_ecore_evas_software_xcb=`${PKG_CONFIG} --variable=XCB evas-software-x11`
+   if test "x$have_ecore_evas_software_xcb" = "xyes" -a "x${have_ecore_x_xcb}" = "xyes" ; then
+      AC_DEFINE(BUILD_ECORE_EVAS_SOFTWARE_XCB, 1, [Evas Software XCB Engine Support])
+   fi
+fi
+
+# ecore_evas_xrender_x11
+
+ECORE_EVAS_CHECK_MODULE([xrender-x11],
+   [${want_ecore_evas_xrender_x11}],
+   [XRender Xlib],
+   [${have_ecore_x_xlib}])
+
+# ecore_evas_opengl_x11
+
+ECORE_EVAS_CHECK_MODULE([opengl-x11],
+   [${want_ecore_evas_opengl_x11}],
+   [OpenGL Xlib],
+   [${have_ecore_x_xlib}])
+
+# ecore_evas_software_x11 16 bits
+
+ECORE_EVAS_CHECK_MODULE([software-16-x11],
+   [${want_ecore_evas_software_16_x11}],
+   [Software Xlib 16 bits],
+   [${have_ecore_x_xlib}])
+
+# ecore_evas_xrender_xcb
+
+ECORE_EVAS_CHECK_MODULE([xrender-xcb],
+   [${want_ecore_evas_xrender_xcb}],
+   [XRender XCB],
+   [${ecore_evas_xcb_deps}])
+
+if test "x$have_ecore_evas_software_x11" = "xyes" -o \
+        "x$have_ecore_evas_xrender_x11" = "xyes" -o \
+        "x$have_ecore_evas_opengl_x11" = "xyes" -o \
+        "x$have_ecore_evas_software_16_x11" = "xyes" -o \
+        "x$have_ecore_evas_software_xcb" = "xyes" -o \
+        "x$have_ecore_evas_xrender_xcb" = "xyes"; then
+   AC_DEFINE(BUILD_ECORE_EVAS_X11, 1, [Support for X Window Engines in Ecore_Evas])
+   requirements_ecore_evas="ecore-x ${requirements_ecore_evas}"
+fi
+
+# ecore_evas_win32
+
+ECORE_EVAS_CHECK_MODULE([software-gdi],
+   [${want_ecore_evas_software_gdi}],
+   [Software GDI],
+   [${have_ecore_win32}])
+
+ECORE_EVAS_CHECK_MODULE([software-ddraw],
+   [${want_ecore_evas_software_ddraw}],
+   [Software DirectDraw],
+   [${have_ecore_win32}])
+
+ECORE_EVAS_CHECK_MODULE([direct3d],
+   [${want_ecore_evas_direct3d}],
+   [Direct3d],
+   [${have_ecore_win32}])
+
+ECORE_EVAS_CHECK_MODULE([opengl-glew],
+   [${want_ecore_evas_opengl_glew}],
+   [Glew OpenGL],
+   [${have_ecore_win32}])
+
+ECORE_EVAS_CHECK_MODULE([software-16-ddraw],
+   [${want_ecore_evas_software_16_ddraw}],
+   [16 bpp Software DirectDraw],
+   [${have_ecore_win32}])
+
+if test "x${have_ecore_evas_software_gdi}" = "xyes" -o \
+        "x${have_ecore_evas_software_ddraw}" = "xyes" -o \
+        "x${have_ecore_evas_direct3d}" = "xyes" -o \
+        "x${have_ecore_evas_opengl_glew}" = "xyes" -o \
+        "x${have_ecore_evas_software_16_ddraw}" = "xyes" ; then
+   AC_DEFINE(BUILD_ECORE_EVAS_WIN32, 1, [Support for Win32 Engine in Ecore_Evas])
+   requirements_ecore_evas="ecore-win32 ${requirements_ecore_evas}"
+fi
+
+# ecore_evas_cocoa
+
+ECORE_EVAS_CHECK_MODULE([cocoa],
+   [${want_ecore_evas_cocoa}],
+   [Cocoa],
+   [${have_ecore_cocoa}],
+   [requirements_ecore_evas="ecore-cocoa ${requirements_ecore_evas}"])
+
+# ecore_evas_software_sdl
+
+ECORE_EVAS_CHECK_MODULE([software-sdl],
+   [${want_ecore_evas_software_sdl}],
+   [Software SDL],
+   [${have_ecore_sdl}],
+   [requirements_ecore_evas="ecore-sdl ${requirements_ecore_evas}"])
+
+# ecore_evas_gl_sdl
+
+ECORE_EVAS_CHECK_MODULE([opengl-sdl],
+   [${want_ecore_evas_gl_sdl}],
+   [OpenGL SDL],
+   [${have_ecore_sdl}],
+   [requirements_ecore_evas="ecore-sdl ${requirements_ecore_evas}"])
+
+# ecore_evas_directfb
+
+ECORE_EVAS_CHECK_MODULE([directfb],
+   [${want_ecore_evas_directfb}],
+   [DirectFB],
+   [${have_ecore_directfb}],
+   [requirements_ecore_evas="ecore-directfb ${requirements_ecore_evas}"])
+
+# ecore_evas_fb
+
+ECORE_EVAS_CHECK_MODULE([fb],
+   [${want_ecore_evas_fb}],
+   [Linux Framebuffer],
+   [${have_ecore_fb}],
+   [requirements_ecore_evas="ecore-fb ${requirements_ecore_evas}"])
+
+# ecore_evas_wince
+
+ECORE_EVAS_CHECK_MODULE([software-16-wince],
+   [${want_ecore_evas_software_16_wince}],
+   [16 bpp Software Windows CE],
+   [${have_ecore_wince}],
+   [requirements_ecore_evas="ecore-wince ${requirements_ecore_evas}"])
+
+
+
+### requirements
+
+AC_SUBST(requirements_ecore)
+AC_SUBST(requirements_ecore_con)
+AC_SUBST(requirements_ecore_config)
+AC_SUBST(requirements_ecore_directfb)
+AC_SUBST(requirements_ecore_evas)
+AC_SUBST(requirements_ecore_fb)
+AC_SUBST(requirements_ecore_file)
+AC_SUBST(requirements_ecore_imf)
+AC_SUBST(requirements_ecore_imf_evas)
+AC_SUBST(requirements_ecore_input)
+AC_SUBST(requirements_ecore_input_evas)
+AC_SUBST(requirements_ecore_ipc)
+AC_SUBST(requirements_ecore_cocoa)
+AC_SUBST(requirements_ecore_sdl)
+AC_SUBST(requirements_ecore_x)
+AC_SUBST(requirements_ecore_win32)
+AC_SUBST(requirements_ecore_wince)
+
+AC_OUTPUT([
+Makefile
+ecore-con.pc
+ecore-config.pc
+ecore-directfb.pc
+ecore-evas.pc
+ecore-fb.pc
+ecore-file.pc
+ecore-cocoa.pc
+ecore-imf.pc
+ecore-imf-evas.pc
+ecore-ipc.pc
+ecore-x.pc
+ecore-input.pc
+ecore-input-evas.pc
+ecore-win32.pc
+ecore-sdl.pc
+ecore-wince.pc
+ecore.pc
+doc/ecore.dox
+doc/Makefile
+src/Makefile
+src/bin/Makefile
+src/lib/Makefile
+src/lib/ecore/Makefile
+src/lib/ecore_con/Makefile
+src/lib/ecore_config/Makefile
+src/lib/ecore_directfb/Makefile
+src/lib/ecore_evas/Makefile
+src/lib/ecore_fb/Makefile
+src/lib/ecore_file/Makefile
+src/lib/ecore_cocoa/Makefile
+src/lib/ecore_sdl/Makefile
+src/lib/ecore_imf/Makefile
+src/lib/ecore_imf_evas/Makefile
+src/lib/ecore_input/Makefile
+src/lib/ecore_input_evas/Makefile
+src/lib/ecore_ipc/Makefile
+src/lib/ecore_win32/Makefile
+src/lib/ecore_wince/Makefile
+src/lib/ecore_x/Makefile
+src/lib/ecore_x/xlib/Makefile
+src/lib/ecore_x/xcb/Makefile
+src/tests/Makefile
+README
+ecore.spec
+po/Makefile.in
+])
+
+echo
+echo "$PACKAGE $VERSION"
+echo
+echo "Optional Modules:"
+echo
+echo " Core:"
+echo
+echo "  Ecore........................: always"
+echo "    Thread support.............: $have_pthread"
+echo "    GLib support...............: $have_glib"
+echo "    Always integrate GLib......: $want_glib_integration_always"
+echo "    Gathering memory statistic.: $have_mallinfo"
+echo "  Ecore_Con....................: $have_ecore_con"
+if test "x$have_ecore_con" = "xyes" ; then
+  echo $ECHO_N "    OpenSSL....................: $have_openssl $ECHO_C"
+if test "x$have_gnutls" = "xyes" ; then
+  echo " (disabled)"
+else
+  echo
+fi
+  echo "    GnuTLS.....................: $have_gnutls"
+  echo "    CURL.......................: $have_curl"
+  echo "    Abstract Sockets...........: $want_abstract_sockets"
+  echo "    c-ares.....................: $have_cares"
+fi
+echo "  Ecore_Ipc....................: $have_ecore_ipc"
+if test "x$have_ecore_ipc" = "xyes" ; then
+  echo $ECHO_N "    OpenSSL....................: $have_openssl $ECHO_C"
+if test "x$have_gnutls" = "xyes" ; then
+  echo " (disabled)"
+else
+  echo
+fi
+  echo "    GnuTLS.....................: $have_gnutls"
+fi
+echo "  Ecore_File...................: $have_ecore_file"
+if test "x$have_ecore_file" = "xyes" ; then
+  echo "    Inotify....................: $have_inotify"
+  echo "    Windows notification.......: $have_notify_win32"
+  echo "    Poll.......................: $have_poll"
+  echo "    CURL.......................: $have_curl"
+fi
+echo "  Ecore_Config.................: $have_ecore_config (deprecated)"
+echo "  Ecore_IMF....................: $have_ecore_imf"
+echo "  Ecore_IMF_Evas...............: $have_ecore_imf_evas"
+echo "  Ecore_Input..................: $have_ecore_input"
+echo "  Ecore_Input_Evas.............: $have_ecore_input_evas"
+
+echo
+echo " Graphic systems:"
+echo
+
+if test "x$have_ecore_x" = "xyes" ; then
+  if test "x$have_ecore_x_xcb" = "xyes" ; then
+    echo "  Ecore_X (XCB backend)........: $have_ecore_x_xcb"
+    echo "    Xprint.....................: $have_ecore_x_xcb_xprint"
+    echo "    Xinerama...................: $have_ecore_x_xcb_xinerama"
+    echo "    Xrandr.....................: $have_ecore_x_xcb_randr"
+    echo "    Xscreensaver...............: $have_ecore_x_xcb_screensaver"
+    echo "    Xshape.....................: $have_ecore_x_xcb_shape"
+    echo "    Xsync......................: $have_ecore_x_xcb_sync"
+    echo "    Xrender....................: $have_ecore_x_xcb_render"
+    echo "    Xcomposite.................: $have_ecore_x_xcb_composite"
+    echo "    Xfixes.....................: $have_ecore_x_xcb_xfixes"
+    echo "    Xdamage....................: $have_ecore_x_xcb_damage"
+    echo "    Xdpms......................: $have_ecore_x_xcb_dpms"
+    echo "    Xtest......................: $have_ecore_x_xcb_xtest"
+  else
+    echo "  Ecore_X (Xlib backend).......: $have_ecore_x"
+    echo "    Xcursor....................: $use_Xcursor"
+    echo "    Xkb........................: $use_xkb"
+    echo "    Xprint.....................: $use_xprint"
+    echo "    Xinerama...................: $use_xinerama"
+    echo "    Xrandr.....................: $use_xrandr"
+    echo "    Xscreensaver...............: $use_xss"
+    echo "    Xrender....................: $use_xrender"
+    echo "    Xcomposite.................: $use_xcomposite"
+    echo "    Xfixes.....................: $use_xfixes"
+    echo "    Xdamage....................: $use_xdamage"
+    echo "    Xdpms......................: $use_xdpms"
+    echo "    Xtest......................: $use_xtest"
+    echo "    XIM........................: $want_xim"
+    echo "    Xi2........................: $use_xi2"
+  fi
+else
+  echo "  Ecore_X......................: $have_ecore_x"
+fi
+echo "  Ecore_Win32..................: $have_ecore_win32"
+echo "  Ecore_Cocoa..................: $have_ecore_cocoa"
+echo "  Ecore_SDL....................: $have_ecore_sdl"
+echo "  Ecore_FB.....................: $have_ecore_fb"
+if test "x${have_ecore_fb}" = "xyes" ; then
+  echo "    Touchscreen................: $have_tslib"
+fi
+echo "  Ecore_DirectFB...............: $have_ecore_directfb"
+echo "  Ecore_WinCE..................: $have_ecore_wince"
+
+echo
+echo " Ecore Evas:"
+echo
+
+echo "  Ecore_Evas...................: $have_ecore_evas"
+if test "x${have_ecore_evas}" = "xyes" ; then
+  echo "    Software Memory Buffer.....: $have_ecore_evas_software_buffer"
+  if test "x${have_ecore_evas_software_x11}" = "xyes" ; then
+    echo "    Software X11...............: $have_ecore_evas_software_x11 (Xlib=${have_ecore_evas_software_xlib}) (XCB=${have_ecore_evas_software_xcb})"
+  else
+    echo "    Software X11...............: $have_ecore_evas_software_x11"
+  fi
+  echo "    XRender X11................: $have_ecore_evas_xrender_x11"
+  echo "    OpenGL X11.................: $have_ecore_evas_opengl_x11"
+  echo "    XRender XCB................: $have_ecore_evas_xrender_xcb"
+  echo "    Software GDI...............: $have_ecore_evas_software_gdi"
+  echo "    Software DirectDraw........: $have_ecore_evas_software_ddraw"
+  echo "    Direct3D...................: $have_ecore_evas_direct3d"
+  echo "    OpenGL Glew................: $have_ecore_evas_opengl_glew"
+  echo "    Cocoa......................: $have_ecore_evas_cocoa"
+  echo "    Software SDL...............: $have_ecore_evas_software_sdl"
+  echo "    OpenGL SDL.................: $have_ecore_evas_opengl_sdl"
+  echo "    DirectFB...................: $have_ecore_evas_directfb"
+  echo "    Software Framebuffer.......: $have_ecore_evas_fb"
+  echo "    Software 16bit X11.........: $have_ecore_evas_software_16_x11"
+  echo "    Software 16bit DirectDraw..: $have_ecore_evas_software_16_ddraw"
+  echo "    Software 16bit WinCE.......: $have_ecore_evas_software_16_wince"
+fi
+echo
+echo "  Tests................: ${enable_tests}"
+echo "  Maximum log level....: ${with_max_log_level}"
+echo "Documentation..........: ${build_doc}"
+echo
+echo "Compilation............: make (or gmake)"
+echo "  CPPFLAGS.............: $CPPFLAGS"
+echo "  CFLAGS...............: $CFLAGS"
+echo "  CXXFLAGS.............: $CXXFLAGS"
+echo "  LDFLAGS..............: $LDFLAGS"
+echo
+echo "Installation...........: make install (as root if needed, with 'su' or 'sudo')"
+echo "  prefix...............: $prefix"
+echo
diff --git a/debian/SVN_REV b/debian/SVN_REV
new file mode 100644 (file)
index 0000000..4cc07a7
--- /dev/null
@@ -0,0 +1,2 @@
+Revision 48959
+Last Changed Rev 48958
diff --git a/debian/_original/changelog b/debian/_original/changelog
new file mode 100644 (file)
index 0000000..659787f
--- /dev/null
@@ -0,0 +1,11 @@
+ecore (0.9.9.060+svnYYYYMMDD-1) unstable; urgency=low
+
+  * New version
+
+ -- quaker <quaker66@gmail.com>  Thu, 22 Apr 2009 18:12:06 +0100
+
+ecore (0.9.9.050+svnYYYYMMDD-1) unstable; urgency=low
+
+  * Clean up changelog
+
+ -- quaker <quaker66@gmail.com>  Tue, 21 Apr 2009 19:14:37 +0100
diff --git a/debian/_original/compat b/debian/_original/compat
new file mode 100644 (file)
index 0000000..1e8b314
--- /dev/null
@@ -0,0 +1 @@
+6
diff --git a/debian/_original/control b/debian/_original/control
new file mode 100644 (file)
index 0000000..2f0169f
--- /dev/null
@@ -0,0 +1,206 @@
+Source: ecore
+Section: libs
+Priority: optional
+Maintainer:  Debian Pkg-e Team <pkg-e-devel@lists.alioth.debian.org>
+Uploaders: Albin Tonnerre <albin.tonnerre@gmail.com>, Niv Sardi <xaiki@debian.org>,
+ Xavier Oswald <x.oswald@free.fr>, Jan Lübbe <jluebbe@debian.org>
+Build-Depends: dpkg-dev (>= 1.14.8), debhelper (>= 6), cdbs, libeina-dev (>= 0.0.2.060+svnYYYYMMDD),
+ libeet-dev (>= 1.0.0), libevas-dev (>= 0.9.9.060+svnYYYYMMDD), libgnutls-dev,
+ libcurl4-gnutls-dev, libxcursor-dev, libxss-dev, libxrender-dev, libxinerama-dev,
+ libxrandr-dev, libxext-dev, libxp-dev, libxcomposite-dev, libjpeg62-dev,
+ libxdamage-dev, x11proto-xext-dev, libxtst-dev, doxygen, pkg-config, libtool
+Standards-Version: 3.8.1
+Homepage: http://enlightenment.org
+
+Package: libecore-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Core abstraction layer for enlightenment DR 0.17
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+
+Package: libecore-con-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore Connection Library
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore Connection Library.
+
+Package: libecore-config-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore Enlightened Property Library
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Enlightened Property Library.
+
+Package: libecore-evas-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore Evas Wrapper Library
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore Evas wrapper functions.
+
+Package: libecore-fb-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore frame buffer system functions
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore frame buffer system functions.
+
+Package: libecore-file-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore File Library
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore File Library.
+
+Package: libecore-imf-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore Input Method Framework module
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore Input Method Framework module, and the Evas
+ helper functions for it.
+
+Package: libecore-input-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore input functions
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore Input Library.
+
+Package: libecore-ipc-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore inter-process communication functions
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore inter-process communication functions.
+
+Package: libecore-x-svn-01
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Ecore functions for dealing with the X Windows System
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains the Ecore wrapper and convenience functions for using
+ the X Windows System.
+
+Package: libecore-dev
+Architecture: any
+Section: libdevel
+Suggests: libecore-doc
+Depends: ${misc:Depends}, libecore-svn-01 (= ${binary:Version}),
+         libecore-con-svn-01 (= ${binary:Version}),
+         libecore-config-svn-01 (= ${binary:Version}),
+         libecore-evas-svn-01 (= ${binary:Version}),
+         libecore-fb-svn-01 (= ${binary:Version}),
+         libecore-file-svn-01 (= ${binary:Version}),
+         libecore-imf-svn-01 (= ${binary:Version}),
+         libecore-input-svn-01 (= ${binary:Version}),
+         libecore-ipc-svn-01 (= ${binary:Version}),
+         libecore-x-svn-01 (= ${binary:Version}),
+         libeet-dev, libevas-dev (>= 0.9.9.060), libeina-dev, pkg-config,
+         libgnutls-dev, libcurl4-gnutls-dev, libxcursor-dev, libxss-dev,
+         libxrender-dev, libxinerama-dev, libxrandr-dev, libxext-dev,
+         libxp-dev, libxcomposite-dev, libxdamage-dev, x11proto-xext-dev, libxtst-dev
+Description: Ecore headers and static libraries
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package contains headers and static libraries for the Ecore library.
+
+Package: libecore-doc
+Architecture: all
+Section: doc
+Depends: ${misc:Depends}
+Enhances: libecore-dev
+Description: Ecore API Documentation
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package provides development documentation (html and manpages)for the
+ Ecore library.
+
+Package: libecore-bin
+Architecture: any
+Section: utils
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: Tools that support Ecore
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications.
+ .
+ This package includes:
+  - ecore_config: allows creation/editing of ecore_config databases
+
+Package: libecore-dbg
+Architecture: any
+Section: libdevel
+Priority: extra
+Depends: ${misc:Depends}, libecore-svn-01 (= ${binary:Version})
+Description: Debugging symbols for libecore
+ This is the core event abstraction layer and X abstraction layer that makes
+ doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
+ handlers fast, optimized, and convenient. It's a separate library so anyone
+ can make use of the work put into Ecore to make this job easy for
+ applications
+ .
+ This package contains unstripped shared libraries. It is provided primarily
+ to provide a backtrace with names in a debugger, this makes it somewhat easier
+ to interpret core dumps. The libraries are installed in /usr/lib/debug and
+ are automatically used by gdb.
diff --git a/debian/_original/copyright b/debian/_original/copyright
new file mode 100644 (file)
index 0000000..57d5703
--- /dev/null
@@ -0,0 +1,44 @@
+This package was debianized by Debian Pkg-e Team <pkg-e-devel@lists.alioth.debian.org> 
+Sat, 07 Jul 2007 09:29:10 +0000.
+
+It was downloaded from http://download.enlightenment.org/
+
+Upstream Authors:
+
+       Enlightenment team <enlightenment-devel@lists.sourceforge.net>
+
+Copyright:
+
+       Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+
+    Additional Copyright:
+    src/lib/ecore/ecore_str.c: Copyright (c) 1998 Todd C. Miller
+        <Todd.Miller@courtesan.com>
+    src/lib/ecore/ecore_value.c: Copyright (C) 2001
+        Christopher Rosendahl <smugg@fatelabs.com>
+        Nathan Ingersoll      <ningerso@d.umn.edu>
+    src/lib/ecore_fb/ecore_fb_li.c: Copyright (C) 1999-2002 Brad Hards
+
+License:
+
+  Permission is hereby granted, free of charge, to any person obtaining a
+  copy of this software and associated documentation files (the "Software"),
+  to deal in the Software without restriction, including without limitation
+  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+  and/or sell copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies of the Software, its documentation and marketing & publicity
+  materials, and acknowledgment shall be given in the documentation,
+  materials and software packages that this Software was used.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+  THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+On Debian systems, the complete text of the BSD License can be found
+in `/usr/share/common-licenses/BSD'.
diff --git a/debian/_original/ecore_config.1 b/debian/_original/ecore_config.1
new file mode 100644 (file)
index 0000000..ea857f4
--- /dev/null
@@ -0,0 +1,54 @@
+.\"Created with GNOME Manpages Editor Wizard
+.\"http://gmanedit.sourceforge.net
+.\"Sergio Rua <srua@gpul.org>
+.\"
+.TH ecore_config 1 "January 18, 2007" "Ecore"
+
+.SH NAME
+ecore_config \-that allow creation and editing of ecore_config databases
+
+.SH SYNOPSIS
+.B ecore_config
+.RI \-a\ |\ \-k\ [\-g|\-d|\-b|\-f|\-i|\-r|\-s|\-t]\ [\-c]
+.br
+
+.SH DESCRIPTION
+.PP
+\fBecore_config\fP is a tool that allows creation and editing of 
+ecore_config databases used by the programs relying on libecore
+
+.SH OPTIONS
+\fIecore_config\fP accepts the following options:
+.TP
+.B \-c, \-\-file=FILE
+Specify the config file to read
+.TP
+.B \-k, \-\-key=KEY
+Select the key KEY. Must be given for all commands except \-a
+.TP
+.B \-g, \-\-get
+get key
+.TP
+.B \-d, \-\-del
+delete key
+.TP
+.B \-b, \-\-bool=VALUE
+set boolean
+.TP
+.B \-f, \-\-float=VALUE
+set float
+.TP
+.B \-i, \-\-int=VALUE
+set integer
+.TP
+.B \-r, \-\-rgb=VALUE
+set RGBA
+.TP
+.B \-s, \-\-string=VALUE
+set string
+.TP
+.B \-t, \-\-theme=VALUE
+set theme
+.SH AUTHOR
+This manual page was written by Albin Tonnerre <albin.tonnerre@gmail.com> 
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/debian/_original/libecore-bin.install b/debian/_original/libecore-bin.install
new file mode 100644 (file)
index 0000000..088dd41
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/bin/ecore_config
diff --git a/debian/_original/libecore-con-svn-01.install b/debian/_original/libecore-con-svn-01.install
new file mode 100644 (file)
index 0000000..4e6f99e
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_con-*.so.*
diff --git a/debian/_original/libecore-con-svn-01.shlibs b/debian/_original/libecore-con-svn-01.shlibs
new file mode 100644 (file)
index 0000000..d5353f3
--- /dev/null
@@ -0,0 +1 @@
+libecore_con-ver-pre-svn-01 0 libecore-con-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-config-svn-01.install b/debian/_original/libecore-config-svn-01.install
new file mode 100644 (file)
index 0000000..d497998
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_config-*.so.*
diff --git a/debian/_original/libecore-config-svn-01.shlibs b/debian/_original/libecore-config-svn-01.shlibs
new file mode 100644 (file)
index 0000000..ec0e971
--- /dev/null
@@ -0,0 +1 @@
+libecore_config-ver-pre-svn-01 0 libecore-config-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-dev.install b/debian/_original/libecore-dev.install
new file mode 100644 (file)
index 0000000..279e512
--- /dev/null
@@ -0,0 +1,14 @@
+debian/tmp/usr/include/Ecore*.h
+debian/tmp/usr/lib/libecore*.a
+debian/tmp/usr/lib/libecore.so
+debian/tmp/usr/lib/libecore_config.so
+debian/tmp/usr/lib/libecore_con.so
+debian/tmp/usr/lib/libecore_evas.so
+debian/tmp/usr/lib/libecore_fb.so
+debian/tmp/usr/lib/libecore_file.so
+debian/tmp/usr/lib/libecore_imf_evas.so
+debian/tmp/usr/lib/libecore_imf.so
+debian/tmp/usr/lib/libecore_input.so
+debian/tmp/usr/lib/libecore_ipc.so
+debian/tmp/usr/lib/libecore_x.so
+debian/tmp/usr/lib/pkgconfig/ecore*.pc
diff --git a/debian/_original/libecore-doc.doc-base b/debian/_original/libecore-doc.doc-base
new file mode 100644 (file)
index 0000000..9ab7e32
--- /dev/null
@@ -0,0 +1,10 @@
+Document: ecore
+Title: Ecore Guide
+Author: Carsten Haitzler
+Abstract: This document describes Ecore API
+ and provides sample C code.
+Section: Programming/C
+
+Format: HTML
+Index: /usr/share/doc/libecore-doc/html/index.html
+Files: /usr/share/doc/libecore-doc/html/*.html
diff --git a/debian/_original/libecore-evas-svn-01.install b/debian/_original/libecore-evas-svn-01.install
new file mode 100644 (file)
index 0000000..ceb9f01
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_evas-*.so.*
diff --git a/debian/_original/libecore-evas-svn-01.shlibs b/debian/_original/libecore-evas-svn-01.shlibs
new file mode 100644 (file)
index 0000000..92c2b6d
--- /dev/null
@@ -0,0 +1 @@
+libecore_evas-ver-pre-svn-01 0 libecore-evas-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-fb-svn-01.install b/debian/_original/libecore-fb-svn-01.install
new file mode 100644 (file)
index 0000000..72ceee2
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_fb-*.so.*
diff --git a/debian/_original/libecore-fb-svn-01.shlibs b/debian/_original/libecore-fb-svn-01.shlibs
new file mode 100644 (file)
index 0000000..2593f16
--- /dev/null
@@ -0,0 +1 @@
+libecore_fb-ver-pre-svn-01 0 libecore-fb-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-file-svn-01.install b/debian/_original/libecore-file-svn-01.install
new file mode 100644 (file)
index 0000000..a115a75
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_file-*.so.*
diff --git a/debian/_original/libecore-file-svn-01.shlibs b/debian/_original/libecore-file-svn-01.shlibs
new file mode 100644 (file)
index 0000000..868a4f6
--- /dev/null
@@ -0,0 +1 @@
+libecore_file-ver-pre-svn-01 0 libecore-file-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-imf-svn-01.install b/debian/_original/libecore-imf-svn-01.install
new file mode 100644 (file)
index 0000000..8da8885
--- /dev/null
@@ -0,0 +1,2 @@
+debian/tmp/usr/lib/libecore_imf-*.so.*
+debian/tmp/usr/lib/libecore_imf_evas-*.so.*
diff --git a/debian/_original/libecore-imf-svn-01.shlibs b/debian/_original/libecore-imf-svn-01.shlibs
new file mode 100644 (file)
index 0000000..15aeb84
--- /dev/null
@@ -0,0 +1,2 @@
+libecore_imf-ver-pre-svn-01 0 libecore-imf-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
+libecore_imf_evas-ver-pre-svn-01 0 libecore-imf-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-input-svn-01.install b/debian/_original/libecore-input-svn-01.install
new file mode 100644 (file)
index 0000000..34d8efb
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_input-*.so.*
diff --git a/debian/_original/libecore-input-svn-01.shlibs b/debian/_original/libecore-input-svn-01.shlibs
new file mode 100644 (file)
index 0000000..b95c6bb
--- /dev/null
@@ -0,0 +1 @@
+libecore_input-ver-pre-svn-01 0 libecore-input-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-ipc-svn-01.install b/debian/_original/libecore-ipc-svn-01.install
new file mode 100644 (file)
index 0000000..e118708
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_ipc-*.so.*
diff --git a/debian/_original/libecore-ipc-svn-01.shlibs b/debian/_original/libecore-ipc-svn-01.shlibs
new file mode 100644 (file)
index 0000000..6a9ae5a
--- /dev/null
@@ -0,0 +1 @@
+libecore_ipc-ver-pre-svn-01 0 libecore-ipc-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-svn-01.install b/debian/_original/libecore-svn-01.install
new file mode 100644 (file)
index 0000000..22c55a3
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore-*.so.*
diff --git a/debian/_original/libecore-svn-01.shlibs b/debian/_original/libecore-svn-01.shlibs
new file mode 100644 (file)
index 0000000..43565e1
--- /dev/null
@@ -0,0 +1 @@
+libecore-ver-pre-svn-01 0 libecore-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/libecore-x-svn-01.install b/debian/_original/libecore-x-svn-01.install
new file mode 100644 (file)
index 0000000..8c8007e
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libecore_x-*.so.*
diff --git a/debian/_original/libecore-x-svn-01.shlibs b/debian/_original/libecore-x-svn-01.shlibs
new file mode 100644 (file)
index 0000000..b5a9660
--- /dev/null
@@ -0,0 +1 @@
+libecore_x-ver-pre-svn-01 0 libecore-x-svn-01 (>= 0.9.9.060+svnYYYYMMDD)
diff --git a/debian/_original/rules b/debian/_original/rules
new file mode 100755 (executable)
index 0000000..a9861f0
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/class/autotools.mk
+include /usr/share/cdbs/1/rules/debhelper.mk
+
+DEB_CONFIGURE_SCRIPT := ./autogen.sh
+DEB_INSTALL_MANPAGES_libecore-bin := debian/ecore_config.1
+DEB_DH_STRIP_ARGS := --dbg-package=libecore-dbg
+DEB_CONFIGURE_EXTRA_FLAGS := --enable-ecore-fb \
+       --disable-ecore-directfb \
+       --disable-ecore-evas-dfb \
+       --enable-ecore-evas-fb \
+       --disable-rpath \
+       --disable-openssl \
+       --enable-gnutls \
+       --enable-doc
+DEB_MAKE_CLEAN_TARGET := distclean
+CFLAGS += -fvisibility=hidden
+LDFLAGS += -fvisibility=hidden
+
+build/libecore-doc::
+       cd $(DEB_SRCDIR)/doc && make doc
+
+install/libecore-doc::
+       mkdir -p debian/libecore-doc/usr/share/doc/libecore-doc
+       cp -R $(DEB_SRCDIR)/doc/html debian/libecore-doc/usr/share/doc/libecore-doc/
+
+clean::
+       [ ! -f Makefile ] || make distclean
+       rm -f ecore-*.tar.bz2 ecore-*.tar.bz2.cdbs-config_list
diff --git a/doc/.cvsignore b/doc/.cvsignore
new file mode 100644 (file)
index 0000000..cc370ed
--- /dev/null
@@ -0,0 +1,3 @@
+html
+latex
+man
diff --git a/doc/Doxyfile b/doc/Doxyfile
new file mode 100644 (file)
index 0000000..f898c07
--- /dev/null
@@ -0,0 +1,138 @@
+PROJECT_NAME           = Ecore
+PROJECT_NUMBER         =
+OUTPUT_DIRECTORY       = .
+INPUT                  = ./ecore.dox ../src/lib
+IMAGE_PATH             = img
+OUTPUT_LANGUAGE        = English
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = head.html
+HTML_FOOTER            = foot.html
+HTML_STYLESHEET        = e.css
+HTML_ALIGN_MEMBERS     = YES
+ENUM_VALUES_PER_LINE   = 1
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = YES
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = NO
+SHOW_INCLUDE_FILES     = NO
+JAVADOC_AUTOBRIEF      = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 2
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = NO
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+FILE_PATTERNS          =
+RECURSIVE              = YES 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = ../examples/
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 2
+IGNORE_PREFIX          = 
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+GENERATE_MAN           = YES
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = YES
+GENERATE_XML           = NO
+XML_SCHEMA             = 
+XML_DTD                = 
+GENERATE_AUTOGEN_DEF   = NO
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = NO
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+CLASS_DIAGRAMS         = NO
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = NO
+COLLABORATION_GRAPH    = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = NO
+INCLUDED_BY_GRAPH      = NO
+GRAPHICAL_HIERARCHY    = NO
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 512
+MAX_DOT_GRAPH_HEIGHT   = 512
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+SEARCHENGINE           = NO
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..0ea8777
--- /dev/null
@@ -0,0 +1,32 @@
+MAINTAINERCLEANFILES = Makefile.in ecore.dox
+
+.PHONY: doc
+
+PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc
+
+if EFL_BUILD_DOC
+
+doc-clean:
+       rm -rf html/ latex/ man/ xml/ $(PACKAGE_DOCNAME).tar*
+
+doc: all doc-clean
+       $(efl_doxygen)
+       cp img/* html/
+       rm -rf $(PACKAGE_DOCNAME).tar*
+       mkdir -p $(PACKAGE_DOCNAME)/doc
+       cp -R html/ latex/ man/ $(PACKAGE_DOCNAME)/doc
+       tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/
+       bzip2 -9 $(PACKAGE_DOCNAME).tar
+       rm -rf $(PACKAGE_DOCNAME)/
+       mv $(PACKAGE_DOCNAME).tar.bz2 $(top_srcdir)
+
+clean-local: doc-clean
+
+else
+
+doc:
+       @echo "Documentation not built. Run ./configure --help"
+
+endif
+
+EXTRA_DIST = Doxyfile $(wildcard img/*.*) e.css head.html foot.html ecore.dox.in
diff --git a/doc/e.css b/doc/e.css
new file mode 100644 (file)
index 0000000..2dd6b44
--- /dev/null
+++ b/doc/e.css
@@ -0,0 +1,273 @@
+/*
+    Author:
+        Andres Blanc <andresblanc@gmail.com>
+       DaveMDS Andreoli <dave@gurumeditation.it>
+
+    Supported Browsers:
+        ie7, opera9, konqueror4 and firefox3
+
+        Please use a different file for ie6, ie5, etc. hacks.
+*/
+
+
+/* Necessary to place the footer at the bottom of the page */
+html, body {
+       height: 100%;
+       margin: 0px;
+       padding: 0px;
+}
+
+#container {
+       min-height: 100%;
+       height: auto !important;
+       height: 100%;
+       margin: 0 auto -53px;
+}
+
+#footer, #push {
+       height: 53px;
+}
+
+
+* html #container {
+       height: 100%;
+}
+
+/* Prevent floating elements overflowing containers */
+.clear {
+       clear: both;
+       width: 0px;
+       height: 0px;
+}
+
+/* Flexible & centered layout from 750 to 960 pixels */
+.layout {
+       max-width: 960px;
+       min-width: 760px;
+       margin-left: auto;
+       margin-right: auto;
+}
+
+body {
+       /*font-family: Lucida Grande, Helvetica, sans-serif;*/
+       font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif
+}
+
+/* Prevent design overflowing the viewport in small resolutions */
+#container {
+       padding-right: 17px;
+       padding-left: 17px;
+       background-image: url(head_bg.png);
+       background-repeat: repeat-x;
+}
+
+/****************************/
+/* Top main menu            */
+/****************************/
+#header_logo {
+   background-image        : url(logo.png);
+   width                   : 61px;
+}
+
+#header_logo a {
+   position                : absolute;
+   border                  : 0px;
+   background-color        : transparent;
+   top                     : 0px;
+   width                   : 60px;
+   height                  : 60px;
+}
+
+#header_menu {
+   background-image        : url(header_menu_background.png);
+   font                    : normal 10pt verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
+   text-align              : right;
+}
+
+#header_last {
+   background-image        : url(header_menu_background_last.png);
+   width                   : 15px;
+}
+
+td.nav_passive {
+   background              : url(header_menu_unselected_background.png) 0 0 no-repeat;
+   height                  : 63px;
+   font-family             : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+   font-size               : 11px;
+   padding                 : 20px 10px 20px 10px;
+   vertical-align          : middle;
+}
+
+td.nav_active {
+   background              : url(header_menu_current_background.png) 0 0 no-repeat;
+   height                  : 63px;
+   color                   : #646464;
+   font-family             : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+   font-size               : 11px;
+   font-weight             : bold;
+   padding                 : 20px 10px 20px 10px;
+   vertical-align          : middle;
+}
+
+#header_menu a {
+   display                 : block;
+   text-decoration         : none;
+   cursor                  : pointer;
+   color                   : #cdcdcd;
+}
+
+
+
+#header {
+       width: 100%;
+       height: 102px;
+}
+
+#header h1 {
+       width: 63px;
+       height: 63px;
+       position: absolute;
+       margin: 0px;
+}
+
+#header h1 span {
+       display: none;
+}
+
+#header h2 {
+       display: none;
+}
+
+/* .menu-container is used to set properties common to .menu and .submenu */
+#header .menu-container {
+}
+
+#header .menu-container ul {
+       list-style-type: none;
+       list-style-position: inside;
+       margin: 0;
+}
+
+#header .menu-container li {
+       display: block;
+       float: right;
+}
+
+#header .menu {
+       height: 63px;
+       display: block;
+       background-image: url(menu_bg.png);
+       background-repeat: repeat-x;
+}
+
+#header .menu ul {
+       height: 100%;
+       display: block;
+       background-image: url(menu_bg_last.png);
+       background-repeat: no-repeat;
+       background-position: top right;
+       padding-right: 17px;
+}
+
+#header .menu li {
+       height: 100%;
+       text-align: center;
+       background-image: url(menu_bg_unsel.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu a {
+       height: 100%;
+       display: block;
+       color: #cdcdcd;
+       text-decoration: none;
+       font-size: 10pt;
+       line-height: 59px;
+       text-align: center;
+       padding: 0px 15px 0px 15px;
+}
+
+#header .menu li:hover {
+       background-image: url(menu_bg_hover.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu li:hover a {
+       color: #FFFFFF;
+}
+
+#header .menu li.current {
+       background-image: url(menu_bg_current.png);
+       background-repeat: no-repeat;
+}
+
+#header .menu li.current a {
+       color: #646464;
+}
+
+
+/* Hide all the submenus but the current */
+#header .submenu ul {
+       display: none;
+}
+
+#header .submenu .current {
+       display: block;
+}
+
+#header .submenu {
+       font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif;
+       margin-top: 10px;
+}
+
+#header .submenu a {
+       color: #888888;
+       text-decoration: none;
+       font-size: 0.9em;
+       line-height: 15px;
+       padding:0px 5px 0px 5px;
+}
+
+#header .submenu a:hover {
+       color: #444444;
+}
+
+#header .submenu li {
+       border-left: 1px solid #DDDDDD;
+}
+
+#header .submenu li:last-child {
+       border-left: 0;
+}
+
+#header .doxytitle {
+       position: absolute;
+       font-size: 1.8em;
+       font-weight: bold;
+       color: #444444;
+       line-height: 35px;
+}
+
+#header small {
+       font-size: 0.4em;
+}
+
+#footer {
+       background-image: url(foot_bg.png);
+       width: 100%;
+}
+
+#footer table {
+       width: 100%;
+       text-align: center;
+       white-space: nowrap;
+       padding: 5px 30px 5px 30px;
+       font-size: 0.8em;
+       font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif;
+       color: #888888;
+}
+
+#footer td.copyright {
+       width: 100%;
+}
+
diff --git a/doc/ecore.dox.in b/doc/ecore.dox.in
new file mode 100644 (file)
index 0000000..d75a8ee
--- /dev/null
@@ -0,0 +1,373 @@
+/** 
+@brief Ecore Library Public API Calls
+These routines are used for Ecore Library interaction
+*/
+
+/**
+
+@mainpage Ecore
+
+@image html  e.png
+
+@version @PACKAGE_VERSION@
+@author Carsten Haitzler <raster\@rasterman.com>
+@author Tom Gilbert <tom\@linuxbrit.co.uk>
+@author Burra <burra\@colorado.edu>
+@author Chris Ross <chris\@darkrock.co.uk>
+@author Term <term\@twistedpath.org>
+@author Tilman Sauerbeck <tilman\@code-monkey.de>
+@author Nathan Ingersoll <rbdpngn\@users.sourceforge.net>
+@date 2000-2004
+
+@section intro Introduction
+
+Ecore is a library of convenience functions.
+
+The Ecore library provides the following modules:
+@li @link Ecore.h        Ecore - Main Loop and Job Functions. @endlink
+@li @link Ecore_Con.h    Ecore_Con - Connection functions. @endlink
+@li @link Ecore_Config.h Ecore_Config - Configuration functions. @endlink
+@li @link Ecore_Evas.h   Ecore_Evas - Evas convenience functions. @endlink
+@li @link Ecore_Fb.h     Ecore_FB - Frame buffer convenience functions. @endlink
+@li @link Ecore_Ipc.h    Ecore_IPC - Inter Process Communication functions. @endlink
+@li @link Ecore_X.h      Ecore_X - X Windows System wrapper. @endlink
+
+@section compiling How to compile using Ecore?
+
+This section has to be documented. Below is just a quick line to handle all
+Ecore modules at once.
+
+@verbatim
+gcc *.c \
+-I/usr/local/include -I/usr/X11R6/include \
+-L/usr/local/lib -L/usr/X11R6/lib \
+-lecore -lecore_evas -lecore_x -lecore_fb \
+`pkg-config evas --cflags --libs`
+@endverbatim
+
+@section install How is it installed?
+
+Suggested configure options for evas for a Linux desktop X display:
+
+@verbatim
+./configure \
+--enable-ecore-x \
+--enable-ecore-fb \
+--enable-ecore-evas \
+--enable-ecore-evas-gl \
+--enable-ecore-con \
+--enable-ecore-ipc
+make CFLAGS="-O9 -mpentiumpro -march=pentiumpro -mcpu=pentiumpro"
+@endverbatim
+
+@todo (1.0) Document API
+
+*/
+
+/*
+@page Ecore_Main_Loop_Page The Ecore Main Loop
+
+@section intro What is Ecore?
+
+Ecore is a clean and tiny event loop library with many modules to do lots of
+convenient things for a programmer, to save time and effort.
+
+It's small and lean, designed to work on embedded systems all the way to
+large and powerful multi-cpu workstations. It serialises all system signals,
+events etc. into a single event queue, that is easily processed without
+needing to worry about concurrency. A properly written, event-driven program
+using this kind of programming doesn't need threads, nor has to worry about
+concurrency. It turns a program into a state machine, and makes it very
+robust and easy to follow.
+
+Ecore gives you other handy primitives, such as timers to tick over for you
+and call specified functions at particular times so the programmer can use
+this to do things, like animate, or time out on connections or tasks that take
+too long etc.
+
+Idle handlers are provided too, as well as calls on entering an idle state
+(often a very good time to update the state of the program). All events that
+enter the system are passed to specific callback functions that the program
+sets up to handle those events. Handling them is simple and other Ecore
+modules produce more events on the queue, coming from other sources such as
+file descriptors etc.
+
+Ecore also lets you have functions called when file descriptors become active
+for reading or writing, allowing for streamlined, non-blocking IO.
+
+Here is an exmaple of a simple program and its basic event loop flow:
+
+@image html  prog_flow.png
+
+
+
+@section work How does Ecore work?
+
+Ecore is very easy to learn and use. All the function calls are designed to
+be easy to remember, explicit in describing what they do, and heavily
+name-spaced. Ecore programs can start and be very simple.
+
+For example:
+
+@code
+#include <Ecore.h>
+
+int main(int argc, const char **argv)
+{
+  ecore_init();
+  ecore_app_args_set(argc, argv);
+  ecore_main_loop_begin();
+  ecore_shutdown();
+  return 0;
+}
+@endcode
+
+This program is very simple and does't check for errors, but it does start up
+and begin a main loop waiting for events or timers to tick off. This program
+doesn't set up any, but now we can expand on this simple program a little
+more by adding some event handlers and timers.
+
+@code
+#include <Ecore.h>
+
+Ecore_Timer         *timer1     = NULL;
+Ecore_Event_Handler *handler1   = NULL;
+double               start_time = 0.0;
+
+int timer_func(void *data)
+{
+  printf("Tick timer. Sec: %3.2f\n", ecore_time_get() - start_time);
+  return 1;
+}
+
+int exit_func(void *data, int ev_type, void *ev)
+{
+  Ecore_Event_Signal_Exit *e;
+
+  e = (Ecore_Event_Signal_Exit *)ev;
+  if (e->interrupt)      printf("Exit: interrupt\n");
+  else if (e->quit)      printf("Exit: quit\n");
+  else if (e->terminate) printf("Exit: terminate\n");
+  ecore_main_loop_quit();
+  return 1;
+}
+
+int main(int argc, const char **argv)
+{
+  ecore_init();
+  ecore_app_args_set(argc, argv);  
+  start_time = ecore_time_get();
+  handler1 = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, exit_func, NULL);
+  timer1 = ecore_timer_add(0.5, timer_func, NULL);  
+  ecore_main_loop_begin();
+  ecore_shutdown();
+  return 0;
+}
+@endcode
+
+In the previous example, we initialize our application and get the time at
+which our program has started so we can calculate an offset. We set
+up a timer to tick off in 0.5 seconds, and since it returns 1, will
+keep ticking off every 0.5 seconds until it returns 0, or is deleted
+by hand. An event handler is set up to call a function - exit_func(),
+whenever an event of type ECORE_EVENT_SIGNAL_EXIT is received (CTRL-C
+on the command line will cause such an event to happen). If this event
+occurs it tells you what kind of exit signal was received, and asks
+the main loop to quit when it is finished by calling
+ecore_main_loop_quit().
+
+The handles returned by ecore_timer_add() and ecore_event_handler_add() are 
+only stored here as an example. If you don't need to address the timer or 
+event handler again you don't need to store the result, so just call the 
+function, and don't assign the result to any variable.
+
+This program looks slightly more complex than needed to do these simple
+things, but in principle, programs don't get any more complex. You add more
+event handlers, for more events, will have more timers and such, BUT it all
+follows the same principles as shown in this example.
+
+*/
+
+/**
+@page Ecore_Config_Page The Enlightened Property Library
+
+The Enlightened Property Library (Ecore_Config) is an adbstraction
+from the complexities of writing your own configuration. It provides
+many features using the Enlightenment 17 development libraries.
+
+To use the library, you:
+@li Set the default values of your properties.
+@li Load the configuration from a file.  You must set the default values
+    first, so that the library knows the correct type of each argument.
+
+The following examples show how to use the Enlightened Property Library:
+@li @link config_basic_example.c config_basic_example.c @endlink
+@li @link config_listener_example.c config_listener_example.c @endlink
+
+*/
+
+/**
+@page Ecore_ADT_Page Ecore Abstract Data Types
+
+This page briefly describes the different abstract data types
+that are provided by the Ecore library for general usage.  You need to
+include the @link Ecore_Data.h Ecore_Data.h @endlink to use them.
+
+@section Ecore_ADT_List List
+
+A list is a simple data type where one each piece of data points to
+another piece of data.
+
+Associated modules that describe the List ADT include:
+@li @ref Ecore_Data_List_Creation_Group
+@li @ref Ecore_Data_List_Add_Item_Group
+@li @ref Ecore_Data_List_Remove_Item_Group
+@li @ref Ecore_Data_List_Traverse_Group
+@li @ref Ecore_Data_List_Node_Group
+
+Examples involving lists include:
+@li @link list_example.c list_example.c @endlink
+
+@section Ecore_ADT_DList Doubly Linked List
+
+A doubly linked list is like a linked list, only each piece of data
+can also point to the piece before it.  In other words, you can traverse
+a doubly linked list in both directions.
+
+Associated modules that describe the DList ADT include:
+@li @ref Ecore_Data_DList_Creation_Group
+@li @ref Ecore_Data_DList_Add_Item_Group
+@li @ref Ecore_Data_DList_Remove_Item_Group
+
+@section Ecore_ADT_Hash Hash
+
+A hash is an abstract data type where one value is associated with another
+value.  Instead of each element of the group being accessible using a
+number, each element is accessed using another object.
+
+Associated modules that describe the Hash ADT include:
+@li @ref Ecore_Data_Hash_ADT_Creation_Group
+@li @ref Ecore_Data_Hash_ADT_Destruction_Group
+@li @ref Ecore_Data_Hash_ADT_Data_Group
+
+@todo Finish this.
+*/
+
+/**
+@page X_Window_System_Page X Window System
+
+The Ecore library includes a wrapper for handling the X window system.
+This page briefly explains what the X window system is and various terms
+that are used.
+*/
+
+// GROUP DEFINITIONS
+
+/**
+@defgroup Ecore_Timer_Group Ecore Timer
+
+The timer allows callbacks to be called at specific intervals.
+ */
+
+/**
+@defgroup Ecore_Job_Group Ecore Jobs
+
+You can queue jobs that are to be done by the main loop when the current
+event is dealt with.
+*/
+
+/**
+@defgroup Idle_Group Idle Handlers
+
+Callbacks that are called when the program enters or exits an idle state.
+
+The ecore main loop enters an idle state when it is waiting for timers
+to time out, data to come in on a file descriptor or any other event
+to occur.  You can set callbacks to be called when the main loop
+enters an idle state, during an idle state or just after the program
+wakes up.
+
+Enterer callbacks are good for updating your program's state, if it
+has a state engine.  Once all of the enterer handlers are called, the
+program will enter a "sleeping" state.
+
+Idler callbacks are called when the main loop has called all enterer
+handlers.  They are useful for interfaces that require polling and
+timers would be too slow to use.
+
+If no idler callbacks are specified, then the process literally goes
+to sleep.  Otherwise, the idler callbacks are called continuously
+while the loop is "idle", using as much CPU as is available to the
+process.
+
+Exiter callbacks are called when the main loop wakes up from an idle
+state.
+
+*/
+
+/**
+@defgroup Ecore_Config_Create_Group Ecore Config Create Functions
+
+Convenience functions that set default values, bounds, option values and
+descriptions in one call.
+*/
+
+/**
+@defgroup Ecore_Config_File_Group Ecore Config File Functions
+
+Functions that are used to load and save properties from and to files.
+*/
+
+// EXAMPLES
+
+/**
+@example args_example.c
+Shows how to set and retrieve the program arguments.
+*/
+
+/**
+@example con_server_example.c
+Shows how to write a simple server using the Ecore_Con library.
+*/
+
+/**
+@example con_client_example.c
+Shows how to write a simple client, that connects to the example server.
+*/
+
+/**
+@example event_handler_example.c
+Shows how to use event handlers.
+*/
+
+/**
+@example timer_example.c
+Demonstrates use of the ecore_timer.
+*/
+
+/**
+@example config_basic_example.c
+Provides an example of how to use the basic configuration functions.
+See the file Ecore_Config.h for the full list of available functions.
+*/
+
+/**
+@example config_listener_example.c
+Shows how to set up a listener to listen for configuration changes.
+*/
+
+/**
+@example list_example.c
+Provides a basic example of how to append to and traverse a list.
+*/
+
+/**
+@example list_destroy_example.c
+Shows how to set and use a destructor for an Ecore_List.
+*/
+
+/**
+@example x_window_example.c
+Shows the basics of using the X Windows system through Ecore functions.
+*/
diff --git a/doc/foot.html b/doc/foot.html
new file mode 100644 (file)
index 0000000..d43cf8f
--- /dev/null
@@ -0,0 +1,18 @@
+ <div id="push"></div>
+ </div> <!-- #content -->
+  </div> <!-- .layout -->
+ </div> <!-- #container -->
+  <div id="footer">
+    <table><tr>
+      <td class="copyright">Copyright &copy;$year Enlightenment</td>
+      <td class="generated">Docs generated $datetime</td>
+    </tr></table>
+  </div>
+
+
+</body>
+</html>
diff --git a/doc/head.html b/doc/head.html
new file mode 100644 (file)
index 0000000..2c61795
--- /dev/null
@@ -0,0 +1,69 @@
+<html>
+<head>
+    <title>$title</title>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
+    <meta name="author" content="Andres Blanc" >
+    
+    <link rel="icon" href="img/favicon.png" type="image/x-icon">
+    <link rel="shortcut icon" href="img/favicon.png" type="image/x-icon">
+    <link rel="icon" href="img/favicon.png" type="image/ico">
+    <link rel="shortcut icon" href="img/favicon.png" type="image/ico">
+
+    <link rel="stylesheet" type="text/css" href="e.css">
+    <link rel="stylesheet" type="text/css" href="edoxy.css">
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="header">
+<div class="layout">
+    
+    <h1><span>Enlightenment</span></h1>
+    <h2><span>Beauty at your fingertips</span></h2>
+
+    <table cellspacing="0" cellpadding="0" width="100%"><tr>
+      <td id="header_logo">
+        <a href="http://www.enlightenment.org"></a>
+      </td>
+      <td id="header_menu">
+        <table cellspacing="0" cellpadding="0" align="right"><tr>
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=home">Home</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=news">News</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=about">About</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=download">Download</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=support">Support</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contribute">Contribute</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contact">Contact</a></td> 
+          <td class="nav_passive"><a class="nav_passive" href="http://trac.enlightenment.org/e">Tracker</a></td>
+          <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=docs">Docs</a></td> 
+        </tr></table>          
+      </td>
+      <td id="header_last"></td>
+    </tr></table>
+
+    <div class="doxytitle">
+        $projectname Documentation <small>at $date</small>
+    </div>
+
+    <div class="menu-container">
+        <div class="submenu">
+            <ul class="current">
+                <li><a href="files.html">Files</a></li>
+                <li><a href="annotated.html">Data Structures</a></li>
+                <li><a href="globals.html">Globals</a></li>
+                <li><a href="modules.html">Modules</a></li>
+                <li><a href="pages.html">Related Pages</a></li>
+               <li class="current"><a  href="index.html">Main Page</a></li>
+            </ul>
+        </div>
+    </div>
+
+
+    <div class="clear"></div>
+</div>
+</div>
+
+<div id="content">
+<div class="layout">
diff --git a/doc/img/e.png b/doc/img/e.png
new file mode 100644 (file)
index 0000000..d42aeb4
Binary files /dev/null and b/doc/img/e.png differ
diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css
new file mode 100644 (file)
index 0000000..311ca23
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * This file contain a custom doxygen style to match e.org graphics
+ */
+
+
+
+/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+       font-family: Geneva, Arial, Helvetica, sans-serif;
+}*/ 
+BODY, TD {
+       font-size: 12px;
+}
+H1 {
+       text-align: center;
+       font-size: 160%;
+}
+H2 {
+       font-size: 120%;
+}
+H3 {
+       font-size: 100%;
+}
+CAPTION { 
+       font-weight: bold 
+}
+DIV.qindex {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navpath {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navtab {
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+TD.navtab {
+       font-size: 70%;
+}
+A.qindex {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D;
+}
+A.qindex:visited {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D
+}
+A.qindex:hover {
+       text-decoration: none;
+       background-color: #ddddff;
+}
+A.qindexHL {
+       text-decoration: none;
+       font-weight: bold;
+       background-color: #6666cc;
+       color: #ffffff;
+       border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+       text-decoration: none;
+       background-color: #6666cc;
+       color: #ffffff;
+}
+A.qindexHL:visited { 
+       text-decoration: none; 
+       background-color: #6666cc; 
+       color: #ffffff 
+}
+A.el { 
+       text-decoration: none; 
+       font-weight: bold 
+}
+A.elRef { 
+       font-weight: bold 
+}
+A.code:link { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.code:visited { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:link { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:visited { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A:hover, A:visited:hover { 
+       text-decoration: none;  
+       /* background-color: #f2f2ff; */
+       color: #000055;
+}
+A.anchor {
+       color: #000;
+}
+DL.el { 
+       margin-left: -1cm 
+}
+.fragment {
+       font-family: monospace, fixed;
+       font-size: 95%;
+}
+PRE.fragment {
+       border: 1px solid #CCCCCC;
+       background-color: #f5f5f5;
+       margin-top: 4px;
+       margin-bottom: 4px;
+       margin-left: 2px;
+       margin-right: 8px;
+       padding-left: 6px;
+       padding-right: 6px;
+       padding-top: 4px;
+       padding-bottom: 4px;
+}
+DIV.ah { 
+       background-color: black; 
+       font-weight: bold; 
+       color: #ffffff; 
+       margin-bottom: 3px; 
+       margin-top: 3px 
+}
+
+DIV.groupHeader {
+       margin-left: 16px;
+       margin-top: 12px;
+       margin-bottom: 6px;
+       font-weight: bold;
+}
+DIV.groupText { 
+       margin-left: 16px; 
+       font-style: italic; 
+       font-size: 90% 
+}
+/*BODY {
+       background: white;
+       color: black;
+       margin-right: 20px;
+       margin-left: 20px;
+}*/
+TD.indexkey {
+       background-color: #e8eef2;
+       font-weight: bold;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+       background-color: #e8eef2;
+       font-style: italic;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TR.memlist {
+       background-color: #f0f0f0; 
+}
+P.formulaDsp { 
+       text-align: center; 
+}
+IMG.formulaDsp {
+}
+IMG.formulaInl { 
+       vertical-align: middle; 
+}
+SPAN.keyword       { color: #008000 }
+SPAN.keywordtype   { color: #604020 }
+SPAN.keywordflow   { color: #e08000 }
+SPAN.comment       { color: #800000 }
+SPAN.preprocessor  { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral   { color: #008080 }
+SPAN.vhdldigit     { color: #ff00ff }
+SPAN.vhdlchar      { color: #000000 }
+SPAN.vhdlkeyword   { color: #700070 }
+SPAN.vhdllogic     { color: #ff0000 }
+
+.mdescLeft {
+       padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.mdescRight {
+        padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.memItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplParams {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       color: #606060;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.search { 
+       color: #003399;
+       font-weight: bold;
+}
+FORM.search {
+       margin-bottom: 0px;
+       margin-top: 0px;
+}
+INPUT.search { 
+       font-size: 75%;
+       color: #000080;
+       font-weight: normal;
+       background-color: #e8eef2;
+}
+TD.tiny { 
+       font-size: 75%;
+}
+a {
+       color: #1A41A8;
+}
+a:visited {
+       color: #2A3798;
+}
+.dirtab { 
+       padding: 4px;
+       border-collapse: collapse;
+       border: 1px solid #84b0c7;
+}
+TH.dirtab { 
+       background: #e8eef2;
+       font-weight: bold;
+}
+HR { 
+       height: 1px;
+       border: none;
+       border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+       font-size: 80%;
+       color: #606060;
+       font-weight: normal;
+       margin-left: 3px;
+} 
+.memnav { 
+       background-color: #eeeeee;
+       border: 1px solid #dddddd;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+.memitem {
+       padding: 4px;
+       background-color: #eeeeee;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #dddddd;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.memname {
+       white-space: nowrap;
+       font-weight: bold;
+        color: #ffffff;
+}
+.memdoc{
+       padding-left: 10px;
+}
+.memproto {
+       background-color: #111111;
+       width: 100%;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #000000;
+       font-weight: bold;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.paramkey {
+       text-align: right;
+       color: #ffffff;
+}
+.paramtype {
+       white-space: nowrap;
+       color: #aaaaaa;
+}
+.paramname {
+       color: #ff0000;
+       font-style: italic;
+       white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+       font-family: sans-serif;
+       margin:0.5em;
+}
+/* these are for tree view when used as main index */
+.directory { 
+       font-size: 9pt; 
+       font-weight: bold; 
+}
+.directory h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+
+/* The following two styles can be used to replace the root node title */
+/* with an image of your choice.  Simply uncomment the next two styles, */
+/* specify the name of your image and be sure to set 'height' to the */
+/* proper pixel height of your image. */
+
+/* .directory h3.swap { */
+/*     height: 61px; */
+/*     background-repeat: no-repeat; */
+/*     background-image: url("yourimage.gif"); */
+/* } */
+/* .directory h3.swap span { */
+/*     display: none; */
+/* } */
+
+.directory > h3 { 
+       margin-top: 0; 
+}
+.directory p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory img { 
+       vertical-align: -30%; 
+}
+/* these are for tree view when not used as main index */
+.directory-alt { 
+       font-size: 100%; 
+       font-weight: bold; 
+}
+.directory-alt h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+.directory-alt > h3 { 
+       margin-top: 0; 
+}
+.directory-alt p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory-alt div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory-alt img { 
+       vertical-align: -30%; 
+}
+
diff --git a/doc/img/elementary.png b/doc/img/elementary.png
new file mode 100644 (file)
index 0000000..7975489
Binary files /dev/null and b/doc/img/elementary.png differ
diff --git a/doc/img/foot_bg.png b/doc/img/foot_bg.png
new file mode 100644 (file)
index 0000000..b24f3a4
Binary files /dev/null and b/doc/img/foot_bg.png differ
diff --git a/doc/img/head_bg.png b/doc/img/head_bg.png
new file mode 100644 (file)
index 0000000..081dc13
Binary files /dev/null and b/doc/img/head_bg.png differ
diff --git a/doc/img/header_menu_background.png b/doc/img/header_menu_background.png
new file mode 100644 (file)
index 0000000..e978743
Binary files /dev/null and b/doc/img/header_menu_background.png differ
diff --git a/doc/img/header_menu_background_last.png b/doc/img/header_menu_background_last.png
new file mode 100644 (file)
index 0000000..88c116c
Binary files /dev/null and b/doc/img/header_menu_background_last.png differ
diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png
new file mode 100644 (file)
index 0000000..de97c92
Binary files /dev/null and b/doc/img/header_menu_current_background.png differ
diff --git a/doc/img/header_menu_unselected_background.png b/doc/img/header_menu_unselected_background.png
new file mode 100644 (file)
index 0000000..50e5fd8
Binary files /dev/null and b/doc/img/header_menu_unselected_background.png differ
diff --git a/doc/img/logo.png b/doc/img/logo.png
new file mode 100644 (file)
index 0000000..b3884a5
Binary files /dev/null and b/doc/img/logo.png differ
diff --git a/doc/img/prog_flow.png b/doc/img/prog_flow.png
new file mode 100644 (file)
index 0000000..06c89c1
Binary files /dev/null and b/doc/img/prog_flow.png differ
diff --git a/ecore-cocoa.pc.in b/ecore-cocoa.pc.in
new file mode 100644 (file)
index 0000000..2194818
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-cocoa
+Description: E core library, Cocoa module
+@pkgconfig_requires_private@: @requirements_ecore_cocoa@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_cocoa
+Cflags: -I${includedir}
diff --git a/ecore-con.pc.in b/ecore-con.pc.in
new file mode 100644 (file)
index 0000000..64f6178
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-con
+Description: E core library, Con module
+@pkgconfig_requires_private@: @requirements_ecore_con@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_con
+Cflags: -I${includedir}
diff --git a/ecore-config.pc.in b/ecore-config.pc.in
new file mode 100644 (file)
index 0000000..dccdee0
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-config
+Description: E core library, Config module
+@pkgconfig_requires_private@: @requirements_ecore_config@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_config
+Cflags: -I${includedir}
diff --git a/ecore-directfb.pc.in b/ecore-directfb.pc.in
new file mode 100644 (file)
index 0000000..f91a8df
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-directfb
+Description: E core library, DirectFB module
+@pkgconfig_requires_private@: @requirements_ecore_directfb@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_directfb
+Cflags: -I${includedir}
diff --git a/ecore-evas.pc.in b/ecore-evas.pc.in
new file mode 100644 (file)
index 0000000..0a21393
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-evas
+Description: E core library, Evas module
+@pkgconfig_requires_private@: @requirements_ecore_evas@
+Version: @VERSION@
+Libs: -L${libdir} @ecore_evas_libs@
+Cflags: -I${includedir}
diff --git a/ecore-fb.pc.in b/ecore-fb.pc.in
new file mode 100644 (file)
index 0000000..3adc295
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-fb
+Description: E core library, FB module
+@pkgconfig_requires_private@: @requirements_ecore_fb@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_fb
+Cflags: -I${includedir}
diff --git a/ecore-file.pc.in b/ecore-file.pc.in
new file mode 100644 (file)
index 0000000..84c10e8
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-file
+Description: E core library, File module
+@pkgconfig_requires_private@: @requirements_ecore_file@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_file
+Cflags: -I${includedir}
diff --git a/ecore-imf-evas.pc.in b/ecore-imf-evas.pc.in
new file mode 100644 (file)
index 0000000..0b160ec
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-imf-evas
+Description: E core library, IMF Evas module
+@pkgconfig_requires_private@: @requirements_ecore_imf_evas@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_imf_evas
+Cflags: -I${includedir}
diff --git a/ecore-imf.pc.in b/ecore-imf.pc.in
new file mode 100644 (file)
index 0000000..926172a
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-imf
+Description: E core library, IMF module
+@pkgconfig_requires_private@: @requirements_ecore_imf@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_imf
+Cflags: -I${includedir}
diff --git a/ecore-input-evas.pc.in b/ecore-input-evas.pc.in
new file mode 100644 (file)
index 0000000..148060a
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-input-evas
+Description: E core library, Input module Evas extension
+@pkgconfig_requires_private@: @requirements_ecore_input_evas@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_input_evas
+Cflags: -I${includedir}
diff --git a/ecore-input.pc.in b/ecore-input.pc.in
new file mode 100644 (file)
index 0000000..81d09b8
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-input
+Description: E core library, Input module
+@pkgconfig_requires_private@: @requirements_ecore_input@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_input
+Cflags: -I${includedir}
diff --git a/ecore-ipc.pc.in b/ecore-ipc.pc.in
new file mode 100644 (file)
index 0000000..5b63f43
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-ipc
+Description: E core library, IPC module
+@pkgconfig_requires_private@: @requirements_ecore_ipc@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_ipc
+Cflags: -I${includedir}
diff --git a/ecore-job.pc.in b/ecore-job.pc.in
new file mode 100644 (file)
index 0000000..83bb7a0
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-job
+Description: E core library, Job module
+@pkgconfig_requires_private@: @requirements_ecore_job@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_job
+Cflags: -I${includedir}
diff --git a/ecore-sdl.pc.in b/ecore-sdl.pc.in
new file mode 100644 (file)
index 0000000..123c8d8
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-sdl
+Description: E core library, SDL module
+@pkgconfig_requires_private@: @requirements_ecore_sdl@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_sdl
+Cflags: -I${includedir}
diff --git a/ecore-win32.pc.in b/ecore-win32.pc.in
new file mode 100644 (file)
index 0000000..b9bf64f
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-win32
+Description: E core library, Win32 module
+@pkgconfig_requires_private@: @requirements_ecore_win32@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_win32
+Libs.private: @ddraw_libs@ @direct3d_libs@
+Cflags: -I${includedir}
diff --git a/ecore-wince.pc.in b/ecore-wince.pc.in
new file mode 100644 (file)
index 0000000..3f5bdc4
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-wince
+Description: E core library, WinCE module
+@pkgconfig_requires_private@: @requirements_ecore_wince@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_wince
+Libs.private: @WIN32_LIBS@
+Cflags: -I${includedir}
diff --git a/ecore-x.pc.in b/ecore-x.pc.in
new file mode 100644 (file)
index 0000000..454a9c3
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-x
+Description: E core library, X module
+@pkgconfig_requires_private@: @requirements_ecore_x@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_x
+Libs.private: @x_libs@ @ecore_x_libs_private@
+Cflags: -I${includedir} @have_ecore_x_xcb_define@
diff --git a/ecore.pc.in b/ecore.pc.in
new file mode 100644 (file)
index 0000000..87ecb6e
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore
+Description: Ecore event abstraction library
+@pkgconfig_requires_private@: @requirements_ecore@
+Version: @VERSION@
+Libs: -L${libdir} -lecore
+Libs.private: -lm
+Cflags: -I${includedir}
diff --git a/ecore.spec.in b/ecore.spec.in
new file mode 100644 (file)
index 0000000..49a4e6b
--- /dev/null
@@ -0,0 +1,231 @@
+# Conditional build stuff; from rpm 4.4 /usr/lib/rpm/macros.
+# bcond_without defaults to WITH, and vice versa.  Yes, it's
+# ass-backward.  Blame PLD.
+# from KainX's changes to evas... 
+%if %{!?with:1}0
+%define with() %{expand:%%{?with_%{1}:1}%%{!?with_%{1}:0}}
+%endif
+%if %{!?without:1}0
+%define without() %{expand:%%{?with_%{1}:0}%%{!?with_%{1}:1}}
+%endif
+%if %{!?bcond_with:1}0
+%define bcond_with() %{expand:%%{?_with_%{1}:%%global with_%{1} 1}}
+%endif
+%if %{!?bcond_without:1}0
+%define bcond_without() %{expand:%%{!?_without_%{1}:%%global with_%{1} 1}}
+%endif
+
+## disabled features
+%bcond_with lib_ecore_directfb
+%bcond_with lib_ecore_sdl
+
+## enabled features
+##%bcond_without module_engine_software_x11
+%bcond_without lib_ecore_fb
+%bcond_without lib_ecore_imf
+
+# This just keeps a missing doxygen from killing the build.
+%define _missing_doc_files_terminate_build 0
+
+%define breq_lib_ecore_directfb     %{?with_lib_ecore_directfb:DirectFB}
+%define breq_lib_ecore_sdl          %{?with_lib_ecore_sdl:SDL-devel}
+
+%define ac_with_lib_ecore_directfb  --%{?with_lib_ecore_directfb:en}%{!?with_lib_ecore_directfb:dis}able-ecore-directfb
+%define ac_with_lib_ecore_fb        --%{?with_lib_ecore_fb:en}%{!?with_lib_ecore_fb:dis}able-ecore-fb
+%define ac_with_lib_ecore_imf       --%{?with_lib_ecore_imf:en}%{!?with_lib_ecore_imf:dis}able-ecore-imf
+%define ac_with_lib_ecore_sdl       --%{?with_lib_ecore_sdl:en}%{!?with_lib_ecore_sdl:dis}able-ecore-sdl
+
+%{!?_rel:%{expand:%%global _rel 0.r%(svnversion | sed 's/[^0-9].*$//' || echo 0000)}}
+
+Summary: Enlightened Core X interface library
+Name: @PACKAGE@
+Version: @VERSION@
+Release: %{_rel}
+License: BSD
+Group: User Interface/X
+Source: %{name}-%{version}.tar.gz
+URL: http://www.enlightenment.org
+Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings <mej@eterm.org>}
+Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)}
+Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
+#BuildSuggests: xorg-x11-devel, XFree86-devel, libX11-devel
+BuildRequires: libjpeg-devel, openssl-devel %{?breq_lib_ecore_directfb}
+BuildRequires: curl-devel, evas-devel, eet-devel %{?breq_lib_ecore_sdl}
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+Ecore is the event/X abstraction layer that makes doing selections,
+Xdnd, general X stuff, event loops, timeouts and idle handlers fast,
+optimized, and convenient. It's a separate library so anyone can make
+use of the work put into Ecore to make this job easy for applications.
+
+%package devel
+Summary: Ecore headers and development libraries.
+Group: Development/Libraries
+Requires: %{name} = %{version}
+Requires: curl-devel, openssl-devel, evas-devel, eet-devel
+Requires: ecore-con, ecore-evas, ecore-file, ecore-ipc
+Requires: ecore-x %{?with_lib_ecore_fb:ecore-fb} %{?with_lib_ecore_directfb:ecore-directfb}
+
+%description devel
+Ecore development files
+
+%package con
+Summary: Ecore Connection Library
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description con
+Ecore Connection Library
+
+%if %{with lib_ecore_directfb}
+%package directfb
+Summary: Ecore DirectFB system functions
+Group: Development/Libraries
+Requires: %{name} = %{version}
+%description directfb
+Ecore DirectFB system functions
+%endif
+
+%package evas
+Summary: Ecore Evas Wrapper Library
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description evas
+Ecore Evas Wrapper Library
+
+%if %{with lib_ecore_fb}
+%package fb
+Summary: Ecore frame buffer system functions
+Group: Development/Libraries
+Requires: %{name} = %{version}
+%description fb
+Ecore frame buffer system functions
+%endif
+
+%package file
+Summary: Ecore File Library
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description file
+Ecore File Library
+
+%if %{with lib_ecore_imf}
+%package imf
+Summary: Ecore IMF functions
+Group: Development/Libraries
+Requires: %{name} = %{version}
+%description imf
+Ecore IMF functions
+%endif
+
+%package input
+Summary: Ecore input functions
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description input
+Ecore input functions
+
+%package ipc
+Summary: Ecore inter-process communication functions
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description ipc
+Ecore inter-process communication functions
+
+%package x
+Summary: Ecore functions for dealing with the X Windows System
+Group: Development/Libraries
+Requires: %{name} = %{version}
+
+%description x
+Ecore functions for dealing with the X Windows System
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+CFLAGS="-I/usr/kerberos/include -I/usr/X11R6/include/X11/extensions"
+LDFLAGS="-L/usr/kerberos/lib -L/usr/X11R6/%{_lib}"
+export CFLAGS LDFLAGS
+%{configure} --prefix=%{_prefix} \
+    %{?ac_with_lib_ecore_directfb} \
+    %{?ac_with_lib_ecore_fb} \
+    %{?ac_with_lib_ecore_imf} \
+    %{?ac_with_lib_ecore_sdl}
+
+%{__make} %{?_smp_mflags} %{?mflags}
+
+%install
+%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install
+%{find_lang} %{name}
+
+%post
+/sbin/ldconfig || :
+
+%postun
+/sbin/ldconfig || :
+
+%clean
+test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
+
+%files -f %{name}.lang
+%defattr(-, root, root)
+%doc AUTHORS COPYING* README*
+%{_libdir}/libecore*.so.*
+
+%files devel
+%defattr(-, root, root)
+%doc doc/html
+%{_libdir}/*.so
+%{_libdir}/*.la
+%{_libdir}/*.a
+%{_libdir}/pkgconfig/*
+#%{_datadir}/aclocal/*
+%{_includedir}/*.h
+
+%files con
+%defattr(-, root, root)
+%{_libdir}/libecore_con*.so.*
+
+%if %{with lib_ecore_directfb}
+%files directfb
+%defattr(-, root, root)
+%{_libdir}/libecore_directfb*.so.*
+%endif
+
+%files evas
+%defattr(-, root, root)
+%{_libdir}/libecore_evas*.so.*
+
+%if %{with lib_ecore_fb}
+%files fb
+%defattr(-, root, root)
+%{_libdir}/libecore_fb*.so.*
+%endif
+
+%files file
+%defattr(-, root, root)
+%{_libdir}/libecore_file*.so.*
+
+%if %{with lib_ecore_imf}
+%files imf
+%defattr(-, root, root)
+%{_libdir}/libecore_imf*.so.*
+%endif
+
+%files input
+%defattr(-, root, root)
+%{_libdir}/libecore_input*.so.*
+
+%files ipc
+%defattr(-, root, root)
+%{_libdir}/libecore_ipc*.so.*
+
+%files x
+%defattr(-, root, root)
+%{_libdir}/libecore_x*.so.*
diff --git a/ecore.supp b/ecore.supp
new file mode 100644 (file)
index 0000000..0b10a6c
--- /dev/null
@@ -0,0 +1,46 @@
+# $Id: ecore.supp 11909 2004-10-19 16:40:25Z tsauerbeck $
+# valgrind suppression file for Ecore
+#
+{
+   BogusLeakError
+   Memcheck:Leak
+   fun:malloc
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_XmbTextPropertyToTextList
+   fun:XmbTextPropertyToTextList
+}
+{
+   bogus2
+   Memcheck:Param
+   write(buf)
+   obj:/lib/ld-2.3.3.so
+   fun:_X11TransWrite
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_XReply
+}
+{
+   bogus3
+   Memcheck:Cond
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_XlcCreateLocaleDataBase
+}
+{
+   bogus4
+   Memcheck:Param
+   write(buf)
+   obj:/lib/ld-2.3.3.so
+   fun:_X11TransWrite
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_XFlush
+}
+{
+   blah, blah, xlib sucks
+   Memcheck:Param
+   writev(vector[...])
+   obj:/lib/ld-2.3.3.so
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_X11TransWritev
+   fun:_XSend
+}
diff --git a/m4/ac_abstract_socket.m4 b/m4/ac_abstract_socket.m4
new file mode 100644 (file)
index 0000000..c4f0b74
--- /dev/null
@@ -0,0 +1,41 @@
+dnl AC_ABSTRACT_SOCKET_TEST(ACTION_IF_FOUND, ACTION_IF_NOT_FOUND)
+dnl test if a system supports the abstract socket namespace
+dnl by rephorm
+AC_DEFUN([AC_ABSTRACT_SOCKET_TEST], [
+AC_MSG_CHECKING(abstract sockets)
+AC_LANG_PUSH(C)
+AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[
+// headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+]],
+[[
+// main fn
+#define ABS_SUN_LEN(s, path) (strlen(path) + 1 + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
+  int fd;
+  struct sockaddr_un sock;
+  char *tmp;
+  char *name = "/ecore/dbus/abstract/test";
+
+  sock.sun_family = AF_UNIX;
+  snprintf(sock.sun_path, sizeof(sock.sun_path), ".%s", name);
+  sock.sun_path[0] = '\0';
+       fd = socket(PF_UNIX, SOCK_STREAM, 0);
+  if (bind(fd, (struct sockaddr *)&sock, ABS_SUN_LEN(&sock, name)) < 0)
+  {
+    printf("Failed to bind to abstract socket.\n");
+    exit(1);
+  }
+
+  printf ("connected\n");
+  exit(0);
+]])],
+[$1],
+[$2])
+])
+
diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4
new file mode 100644 (file)
index 0000000..23479a9
--- /dev/null
@@ -0,0 +1,47 @@
+dnl Copyright (C) 2004-2008 Kim Woelders
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+dnl Originally snatched from somewhere...
+
+dnl Macro for checking if the compiler supports __attribute__
+
+dnl Usage: AC_C___ATTRIBUTE__
+dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
+dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
+dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
+dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
+dnl defined to nothing.
+
+AC_DEFUN([AC_C___ATTRIBUTE__],
+[
+
+AC_MSG_CHECKING([for __attribute__])
+
+AC_CACHE_VAL([ac_cv___attribute__],
+   [AC_TRY_COMPILE(
+       [
+#include <stdlib.h>
+
+int func(int x);
+int foo(int x __attribute__ ((unused)))
+{
+   exit(1);
+}
+       ],
+       [],
+       [ac_cv___attribute__="yes"],
+       [ac_cv___attribute__="no"]
+    )])
+
+AC_MSG_RESULT($ac_cv___attribute__)
+
+if test "x${ac_cv___attribute__}" = "xyes" ; then
+   AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
+   AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
+  else
+    AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
+fi
+
+])
+
+dnl End of ac_attribute.m4
diff --git a/m4/check_x_extension.m4 b/m4/check_x_extension.m4
new file mode 100644 (file)
index 0000000..a15120c
--- /dev/null
@@ -0,0 +1,40 @@
+dnl use: ECORE_CHECK_X_EXTENSION(Foo, header, lib, func, want)
+AC_DEFUN([ECORE_CHECK_X_EXTENSION],
+[
+pushdef([UP], translit([$1], [a-z], [A-Z]))dnl
+pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl
+
+UP[]_CFLAGS=""
+UP[]_LIBS=""
+use_[]DOWN="no"
+
+if test "x$5" != "xno"; then
+  SAVE_CFLAGS=$CFLAGS
+  CFLAGS="$x_cflags $x_includes"
+  AC_CHECK_HEADER(X11/extensions/$2,
+    [
+     AC_CHECK_LIB($3, $4,
+       [
+        AC_DEFINE(ECORE_[]UP, 1, [Build support for $1])
+        UP[]_LIBS="-l$3"
+        use_[]DOWN="yes"
+       ],
+       [ use_[]DOWN="no" ],
+       [ $x_libs ]
+     )
+    ],
+    [ use_[]DOWN="no" ],
+    [ #include <X11/Xlib.h> ]
+  )
+  CFLAGS=$SAVE_CFLAGS
+else
+  use_[]DOWN="no"
+  AC_MSG_NOTICE([$1 support disabled])
+fi
+
+AC_SUBST(UP[]_CFLAGS)
+AC_SUBST(UP[]_LIBS)
+
+popdef([UP])
+popdef([DOWN])
+])
diff --git a/m4/ecore_check_module.m4 b/m4/ecore_check_module.m4
new file mode 100644 (file)
index 0000000..3980e5b
--- /dev/null
@@ -0,0 +1,93 @@
+dnl use: ECORE_CHECK_MODULE(Foo, default-enabled, description[, dependancy[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]])
+AC_DEFUN([ECORE_CHECK_MODULE],
+[
+m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
+m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
+
+have_ecore_[]m4_defn([DOWN])=no
+ecore_[]m4_defn([DOWN])[]_cflags=
+ecore_[]m4_defn([DOWN])[]_libs=
+want_module=$2
+
+AC_ARG_ENABLE(ecore-$1,
+   [AC_HELP_STRING(
+       [--enable-ecore-$1],
+       [enable the ecore_]m4_defn([DOWN])[ module])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_module="yes"
+    else
+       want_module="no"
+    fi
+   ],
+   [])
+
+AC_MSG_CHECKING([whether Ecore_$3 module is to be built])
+
+if test "x${want_module}" = "xyes" ; then
+   if test "x$4" = "x" || test "x$4" = "xyes" ; then
+      AC_DEFINE([BUILD_ECORE_]m4_defn([UP]), [1], [Build Ecore_$3 Module])
+      have_ecore_[]m4_defn([DOWN])="yes"
+      ecore_[]m4_defn([DOWN])[]_libs="-lecore_[]m4_defn([DOWN])"
+      AC_MSG_RESULT([yes])
+   else
+      AC_MSG_RESULT([no (dependency failed)])
+   fi
+else
+   AC_MSG_RESULT([no])
+fi
+
+AM_CONDITIONAL([BUILD_ECORE_]UP, [test "x$have_ecore_]DOWN[" = "xyes"])
+
+AS_IF([test "x$have_ecore_[]m4_defn([DOWN])" = "xyes"], [$5], [$6])
+
+AC_SUBST(ecore_[]m4_defn([DOWN])[]_cflags)
+AC_SUBST(ecore_[]m4_defn([DOWN])[]_libs)
+
+m4_popdef([UP])
+m4_popdef([DOWN])
+])
+
+dnl use: ECORE_EVAS_CHECK_MODULE(foo-bar, want, description, backend[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_EVAS_CHECK_MODULE],
+[
+m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
+m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
+
+have_ecore_evas_[]m4_defn([DOWN])="no"
+want_module="$2"
+
+AC_ARG_ENABLE(ecore-evas-$1,
+   [AC_HELP_STRING(
+       [--enable-ecore-evas-$1],
+       [enable $3 support in the ecore_evas module.])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_module="yes"
+    else
+       want_module="no"
+    fi
+   ],
+   [])
+
+AC_MSG_CHECKING([whether ecore_evas $3 support is to be built])
+AC_MSG_RESULT([${want_module}])
+
+if test "x$4" = "xyes" -a \
+        "x$have_ecore_evas" = "xyes" -a \
+        "x$want_module" = "xyes" ; then
+   PKG_CHECK_EXISTS([evas-$1],
+      [
+       AC_DEFINE([BUILD_ECORE_EVAS_]m4_defn([UP]), [1], [Support for $3 Engine in Ecore_Evas])
+       have_ecore_evas_[]m4_defn([DOWN])="yes"
+      ])
+fi
+
+AC_MSG_CHECKING([whether ecore_evas $3 support is built])
+AC_MSG_RESULT([$have_ecore_evas_]m4_defn([DOWN]))
+
+AS_IF([test "x$have_ecore_evas_[]m4_defn([DOWN])" = "xyes"], [$5], [$6])
+
+m4_popdef([UP])
+m4_popdef([DOWN])
+])
diff --git a/m4/ecore_check_options.m4 b/m4/ecore_check_options.m4
new file mode 100644 (file)
index 0000000..054ab0b
--- /dev/null
@@ -0,0 +1,319 @@
+dnl use: ECORE_CHECK_POLL(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_POLL],
+[
+_ecore_want_poll=$1
+_ecore_have_poll="no"
+
+AC_ARG_ENABLE(poll,
+   [AC_HELP_STRING([--disable-poll], [disable poll in the ecore_file module])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_poll="yes"
+    else
+       _ecore_want_poll="no"
+    fi
+   ])
+
+AC_MSG_CHECKING(whether polling is to be used for filemonitoring)
+AC_MSG_RESULT(${_ecore_want_poll})
+
+if test "x${_ecore_want_poll}" = "xyes" ; then
+   AC_DEFINE([HAVE_POLL], [1], [ File monitoring with polling ])
+   _ecore_have_poll="yes"
+fi
+
+if test "x${_ecore_have_poll}" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+
+dnl use: ECORE_CHECK_INOTIFY(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_INOTIFY],
+[
+_ecore_want_inotify=$1
+_ecore_have_inotify="no"
+
+dnl We need to check if the right inotify version is accessible
+_ecore_want_inotify="yes"
+AC_ARG_ENABLE(inotify,
+   [AC_HELP_STRING([--disable-inotify], [disable inotify in the ecore_file module])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_inotify="yes"
+    else
+       _ecore_want_inotify="no"
+    fi
+   ])
+
+AC_MSG_CHECKING(whether inotify is to be used for filemonitoring)
+AC_MSG_RESULT($_ecore_want_inotify)
+
+dnl It is hard to find a good test on how to check the correct
+dnl inotify version. They changed the headers a lot.
+dnl in kernel 2.6.13 __NR_inotify_init was added to the defined syscalls
+dnl in asm/unistd.h and IN_MOVE_SELF was added to linux/inotify.h
+dnl so with this check you need a very new kernel and kernel-headers!
+
+if test "x${_ecore_want_inotify}" = "xyes" ; then
+   AC_CHECK_LIB([c], [inotify_init],
+      [
+       AC_DEFINE(HAVE_INOTIFY, 1, [ File monitoring with Inotify ])
+       AC_DEFINE(HAVE_SYS_INOTIFY, 1, [ File monitoring with Inotify - sys/inotify.h ])
+       _ecore_have_inotify="yes"
+      ],
+      [
+       AC_TRY_COMPILE(
+          [
+           #include <asm/unistd.h>
+           #include <linux/inotify.h>
+          ],
+          [int a = __NR_inotify_init; int b = IN_MOVE_SELF;],
+          [
+           AC_DEFINE([HAVE_INOTIFY], [1], [ File monitoring with Inotify ])
+           _ecore_have_inotify="yes"
+          ],
+          [_ecore_have_inotify="no"])
+      ])
+fi
+
+if test "x$_ecore_have_inotify" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+dnl use: ECORE_CHECK_NOTIFY_WIN32(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_NOTIFY_WIN32],
+[
+_ecore_want_notify_win32=$1
+_ecore_have_notify_win32="no"
+
+AC_ARG_ENABLE(notify-win32,
+   [AC_HELP_STRING([--disable-notify-win32], [disable Windows notification in the ecore_file module])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_notify_win32="yes"
+    else
+       _ecore_want_notify_win32="no"
+    fi
+   ])
+
+AC_MSG_CHECKING(whether Windows notification is to be used for filemonitoring)
+AC_MSG_RESULT(${_ecore_want_notify_win32})
+
+if test "x${_ecore_want_notify_win32}" = "xyes" ; then
+   AC_DEFINE([HAVE_NOTIFY_WIN32], [1], [ File monitoring with Windows notification ])
+   _ecore_have_notify_win32="yes"
+fi
+
+if test "x${_ecore_have_notify_win32}" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+
+dnl use: ECORE_CHECK_CURL(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_CURL],
+[
+_ecore_want_curl=$1
+_ecore_have_curl="no"
+
+AC_ARG_ENABLE([curl],
+   [AC_HELP_STRING([--disable-curl], [disable curl support])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_curl="yes"
+    else
+       _ecore_want_curl="no"
+    fi
+   ])
+
+if test "x${_ecore_want_curl}" = "xyes" ; then
+   PKG_CHECK_MODULES(CURL, libcurl,
+      [
+       AC_DEFINE(HAVE_CURL, 1, [ Downloading with CURL ])
+       _ecore_have_curl="yes"
+      ],
+      [_ecore_have_curl="no"])
+fi
+
+if test "x$_ecore_have_curl" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+
+dnl use: ECORE_CHECK_GNUTLS(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_GNUTLS],
+[
+_ecore_want_gnutls=$1
+_ecore_have_gnutls="no"
+
+AC_ARG_ENABLE([gnutls],
+   [AC_HELP_STRING([--disable-gnutls], [disable gnutls support])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_gnutls="yes"
+    else
+       _ecore_want_gnutls="no"
+    fi
+   ])
+
+if test "x${_ecore_want_gnutls}" = "xyes" -o "x${_ecore_want_gnutls}" = "xauto" ; then
+   PKG_CHECK_MODULES([TLS], [gnutls],
+      [
+       AC_DEFINE([USE_GNUTLS], [1], [Use GnuTLS])
+       _ecore_have_gnutls="yes"
+      ],
+      [_ecore_have_gnutls="no"])
+   # for ecore_con_ssl.c
+   PKG_CHECK_MODULES([TLS2], [gnutls >= 2.0.0],
+      [AC_DEFINE(USE_GNUTLS2, 1, [Use GnuTLS 2 or higher])],
+      [dummy="no"])
+fi
+
+if test "x$_ecore_have_gnutls" = "xyes" ; then
+  ifelse([$2], , :, [$2])
+else
+  ifelse([$3], , :, [$3])
+fi
+])
+
+dnl use: ECORE_CHECK_OPENSSL(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_OPENSSL],
+[
+_ecore_want_openssl=$1
+_ecore_have_openssl="no"
+
+AC_ARG_ENABLE(openssl,
+  [AC_HELP_STRING([--disable-openssl], [disable openssl support])],
+  [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_openssl="yes"
+    else
+       _ecore_want_openssl="no"
+    fi
+  ])
+
+if test "x${_ecore_want_openssl}" = "xyes" -o "x${_ecore_want_openssl}" = "xauto"; then
+   PKG_CHECK_MODULES([SSL],
+      [openssl],
+      [
+       AC_DEFINE(USE_OPENSSL, 1, [Use OpenSSL])
+       _ecore_have_openssl="yes"
+      ],
+      [_ecore_have_openssl="no"])
+fi
+
+if test "x$_ecore_have_openssl" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+
+dnl use: ECORE_CHECK_TSLIB(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_TSLIB],
+[
+_tslib_requirement=""
+_ecore_want_tslib=$1
+_ecore_have_tslib="no"
+TSLIB_LIBS=""
+TSLIB_CFLAGS=""
+
+AC_ARG_ENABLE([tslib],
+   [AC_HELP_STRING([--disable-tslib],
+       [disable the tslib support in ecore (currently ecore-fb).
+        @<:@default=detect@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_tslib="yes"
+    else
+       _ecore_want_tslib="no"
+    fi
+   ])
+
+if test "x${_ecore_want_tslib}" = "xyes" -o "x${_ecore_want_tslib}" = "xauto" ; then
+   PKG_CHECK_MODULES([TSLIB], [tslib-1.0],
+     [
+      AC_DEFINE(HAVE_TSLIB, 1, [Build Ecore_FB Touchscreen Code])
+      _ecore_have_tslib="yes"
+      _tslib_requirement="tslib-1.0"
+     ],[
+      PKG_CHECK_MODULES([TSLIB], [tslib],
+        [
+         AC_DEFINE(HAVE_TSLIB, 1, [Build Ecore_FB Touchscreen Code])
+         _ecore_have_tslib="yes"
+         _tslib_requirement="tslib"
+        ],[
+         AC_CHECK_HEADER([tslib.h],
+           [
+            AC_CHECK_LIB([ts], [ts_open], 
+              [
+               TSLIB_LIBS="-lts" 
+               TSLIB_CFLAGS=""
+               AC_DEFINE(HAVE_TSLIB, 1, [Build Ecore_FB Touchscreen Code])
+               _ecore_have_tslib="yes"
+              ],[
+               AC_CHECK_LIB([tslib], [ts_open],
+                 [
+                  TSLIB_LIBS="-ltslib"
+                  TSLIB_CFLAGS=""
+                  AC_DEFINE(HAVE_TSLIB, 1, [Build Ecore_FB Touchscreen Code])
+                  _ecore_have_tslib="yes"
+                 ],[
+                  _ecore_have_tslib="no"
+                 ])
+              ])
+           ])
+        ])
+     ])
+fi
+
+AC_SUBST(TSLIB_LIBS)
+AC_SUBST(TSLIB_CFLAGS)
+
+if test "x$_ecore_have_tslib" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
+
+dnl use: ECORE_CHECK_CARES(default-enabled[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([ECORE_CHECK_CARES],
+[
+_ecore_want_cares=$1
+_ecore_have_cares="no"
+
+AC_ARG_ENABLE(cares,
+  [AC_HELP_STRING([--disable-cares], [disable cares support])],
+  [
+    if test "x${enableval}" = "xyes" ; then
+       _ecore_want_cares="yes"
+    else
+       _ecore_want_cares="no"
+    fi
+  ])
+
+if test "x${_ecore_want_cares}" = "xyes" -o "x${_ecore_want_cares}" = "xauto" ; then
+   PKG_CHECK_MODULES([CARES], [libcares >= 1.6.1],
+     [_ecore_have_cares="yes"],
+     [_ecore_have_cares="no"])
+fi
+
+if test "x${_ecore_have_cares}" = "xyes" ; then
+   AC_DEFINE([HAVE_CARES], [1], [Build Ecore_Con_Info with c-ares support])
+fi
+
+if test "x$_ecore_have_cares" = "xyes" ; then
+   m4_default([$2], [:])
+else
+   m4_default([$3], [:])
+fi
+])
diff --git a/m4/efl_doxygen.m4 b/m4/efl_doxygen.m4
new file mode 100644 (file)
index 0000000..d83ed68
--- /dev/null
@@ -0,0 +1,97 @@
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if doxygen is available or not.
+
+dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Test for the doxygen program
+dnl Defines efl_doxygen
+dnl Defines the automake conditionnal EFL_BUILD_DOC
+dnl
+AC_DEFUN([EFL_CHECK_DOXYGEN],
+[
+
+dnl
+dnl Disable the build of the documentation
+dnl
+AC_ARG_ENABLE([doc],
+   [AC_HELP_STRING(
+       [--disable-doc],
+       [Disable documentation build @<:@default=enabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       efl_enable_doc="yes"
+    else
+       efl_enable_doc="no"
+    fi
+   ],
+   [efl_enable_doc="yes"])
+
+AC_MSG_CHECKING([whether to build documentation])
+AC_MSG_RESULT([${efl_enable_doc}])
+
+if test "x${efl_enable_doc}" = "xyes" ; then
+
+dnl Specify the file name, without path
+
+   efl_doxygen="doxygen"
+
+   AC_ARG_WITH([doxygen],
+      [AC_HELP_STRING(
+          [--with-doxygen=FILE],
+          [doxygen program to use @<:@default=doxygen@:>@])],
+
+dnl Check the given doxygen program.
+
+      [efl_doxygen=${withval}
+       AC_CHECK_PROG([efl_have_doxygen],
+          [${efl_doxygen}],
+          [yes],
+          [no])
+       if test "x${efl_have_doxygen}" = "xno" ; then
+          echo "WARNING:"
+          echo "The doxygen program you specified:"
+          echo "${efl_doxygen}"
+          echo "was not found.  Please check the path and make sure "
+          echo "the program exists and is executable."
+          AC_MSG_WARN([no doxygen detected. Documentation will not be built])
+       fi
+      ],
+      [AC_CHECK_PROG([efl_have_doxygen],
+          [${efl_doxygen}],
+          [yes],
+          [no])
+       if test "x${efl_have_doxygen}" = "xno" ; then
+          echo "WARNING:"
+          echo "The doxygen program was not found in your execute path."
+          echo "You may have doxygen installed somewhere not covered by your path."
+          echo ""
+          echo "If this is the case make sure you have the packages installed, AND"
+          echo "that the doxygen program is in your execute path (see your"
+          echo "shell manual page on setting the \$PATH environment variable), OR"
+          echo "alternatively, specify the program to use with --with-doxygen."
+          AC_MSG_WARN([no doxygen detected. Documentation will not be built])
+       fi
+      ])
+fi
+
+dnl
+dnl Substitution
+dnl
+AC_SUBST([efl_doxygen])
+
+if ! test "x${efl_have_doxygen}" = "xyes" ; then
+   efl_enable_doc="no"
+fi
+
+AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_enable_doc}" = "xyes")
+
+if test "x${efl_enable_doc}" = "xyes" ; then
+  m4_default([$1], [:])
+else
+  m4_default([$2], [:])
+fi
+
+])
+
+dnl End of efl_doxygen.m4
diff --git a/m4/efl_path_max.m4 b/m4/efl_path_max.m4
new file mode 100644 (file)
index 0000000..f57bfd2
--- /dev/null
@@ -0,0 +1,36 @@
+dnl Check for PATH_MAX in limits.h, and define a default value if not found
+dnl This is a workaround for systems not providing PATH_MAX, like GNU/Hurd
+
+dnl EFL_CHECK_PATH_MAX([DEFAULT_VALUE_IF_NOT_FOUND])
+dnl
+dnl If PATH_MAX is not defined in <limits.h>, defines it
+dnl to DEFAULT_VALUE_IF_NOT_FOUND if it exists, or fallback
+dnl to using 4096
+
+AC_DEFUN([EFL_CHECK_PATH_MAX],
+[
+
+default_max=m4_default([$1], "4096")
+AC_LANG_PUSH([C])
+
+AC_MSG_CHECKING([for PATH_MAX in limits.h])
+AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(
+       [[
+#include <limits.h>
+       ]],
+       [[
+int i = PATH_MAX;
+       ]])],
+   [AC_MSG_RESULT([yes])],
+   [
+    AC_DEFINE_UNQUOTED([PATH_MAX],
+       [${default_max}],
+       [default value since PATH_MAX is not defined])
+    AC_MSG_RESULT([no: using ${default_max}])
+   ])
+
+AC_LANG_POP([C])
+
+])
+dnl end of efl_path_max.m4
diff --git a/m4/efl_pthread.m4 b/m4/efl_pthread.m4
new file mode 100644 (file)
index 0000000..1894ad7
--- /dev/null
@@ -0,0 +1,130 @@
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if several pthread library is available or not.
+
+dnl Usage: EFL_CHECK_PTHREAD(want_pthread_spin[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS)
+dnl Call AC_SUBST(EFL_PTHREAD_LIBS)
+dnl Define EFL_HAVE_PTHREAD
+dnl Define EFL_HAVE_PTHREAD_SPINLOCK
+
+AC_DEFUN([EFL_CHECK_PTHREAD],
+[
+
+dnl configure option
+
+AC_ARG_ENABLE([pthread],
+   [AC_HELP_STRING([--disable-pthread], [enable POSIX threads code @<:@default=auto@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _efl_enable_pthread="yes"
+    else
+       _efl_enable_pthread="no"
+    fi
+   ],
+   [_efl_enable_pthread="auto"])
+
+AC_MSG_CHECKING([whether to build POSIX threads code])
+AC_MSG_RESULT([${_efl_enable_pthread}])
+
+dnl check if the compiler supports pthreads
+
+case "$host_os" in
+   mingw*)
+      _efl_pthread_cflags=""
+      _efl_pthread_libs="-lpthreadGC2"
+      ;;
+   solaris*)
+      _efl_pthread_cflags="-mt"
+      _efl_pthread_libs="-mt"
+      ;;
+   *)
+      _efl_pthread_cflags="-pthread"
+      _efl_pthread_libs="-pthread"
+      ;;
+esac
+
+_efl_have_pthread="no"
+
+if test "x${_efl_enable_pthread}" = "xyes" || test "x${_efl_enable_pthread}" = "xauto" ; then
+
+   SAVE_CFLAGS=${CFLAGS}
+   CFLAGS="${CFLAGS} ${_efl_pthread_cflags}"
+   SAVE_LDFLAGS=${LDFLAGS}
+   LDFLAGS="${LDFLAGS} ${_efl_pthread_libs}"
+   AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[
+#include <pthread.h>
+                       ]],
+                       [[
+pthread_t id;
+id = pthread_self();
+                       ]])],
+      [_efl_have_pthread="yes"],
+      [_efl_have_pthread="no"])
+   CFLAGS=${SAVE_CFLAGS}
+   LDFLAGS=${SAVE_LDFLAGS}
+
+fi
+
+AC_MSG_CHECKING([whether system support POSIX threads])
+AC_MSG_RESULT([${_efl_have_pthread}])
+if test "$x{_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread}" = "xno"; then
+   AC_MSG_ERROR([pthread support requested but not found.])
+fi
+
+EFL_PTHREAD_CFLAGS=""
+EFL_PTHREAD_LIBS=""
+if test "x${_efl_have_pthread}" = "xyes" ; then
+   EFL_PTHREAD_CFLAGS=${_efl_pthread_cflags}
+   EFL_PTHREAD_LIBS=${_efl_pthread_libs}
+fi
+
+AC_SUBST(EFL_PTHREAD_CFLAGS)
+AC_SUBST(EFL_PTHREAD_LIBS)
+
+if test "x${_efl_have_pthread}" = "xyes" ; then
+   AC_DEFINE(EFL_HAVE_PTHREAD, 1, [Define to mention that POSIX threads are supported])
+fi
+
+dnl check if the compiler supports pthreads spinlock
+
+_efl_have_pthread_spinlock="no"
+
+if test "x${_efl_have_pthread}" = "xyes" && test "x$1" = "xyes" ; then
+
+   SAVE_CFLAGS=${CFLAGS}
+   CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}"
+   SAVE_LDFLAGS=${LDFLAGS}
+   LDFLAGS="${LDFLAGS} ${EFL_PTHREAD_LIBS}"
+   AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[
+#include <pthread.h>
+                       ]],
+                       [[
+pthread_spinlock_t lock;
+int res;
+res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
+                       ]])],
+      [_efl_have_pthread_spinlock="yes"],
+      [_efl_have_pthread_spinlock="no"])
+   CFLAGS=${SAVE_CFLAGS}
+   LDFLAGS=${SAVE_LDFLAGS}
+
+fi
+
+AC_MSG_CHECKING([whether to build POSIX threads spinlock code])
+AC_MSG_RESULT([${_efl_have_pthread_spinlock}])
+if test "x${_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread_spinlock}" = "xno" && test "x$1" = "xyes" ; then
+   AC_MSG_WARN([pthread support requested but spinlocks are not supported])
+fi
+
+if test "x${_efl_have_pthread_spinlock}" = "xyes" ; then
+   AC_DEFINE(EFL_HAVE_PTHREAD_SPINLOCK, 1, [Define to mention that POSIX threads spinlocks are supported])
+fi
+
+AS_IF([test "x$_efl_have_pthread" = "xyes"], [$2], [$3])
+AS_IF([test "x$_efl_have_pthread_spinlock" = "xyes"], [$4], [$5])
+
+])
diff --git a/m4/efl_tests.m4 b/m4/efl_tests.m4
new file mode 100644 (file)
index 0000000..3a4dfe2
--- /dev/null
@@ -0,0 +1,43 @@
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if tests programs are wanted and if yes, if
+dnl the Check library is available.
+
+dnl Usage: EFL_CHECK_TESTS([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Define the automake conditionnal EFL_ENABLE_TESTS
+
+AC_DEFUN([EFL_CHECK_TESTS],
+[
+
+dnl configure option
+
+AC_ARG_ENABLE([tests],
+   [AC_HELP_STRING([--enable-tests], [enable tests @<:@default=disabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       _efl_enable_tests="yes"
+    else
+       _efl_enable_tests="no"
+    fi
+   ],
+   [_efl_enable_tests="no"])
+
+AC_MSG_CHECKING([whether tests are built])
+AC_MSG_RESULT([${_efl_enable_tests}])
+
+AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+
+if test "x${_efl_enable_tests}" = "xyes" ; then
+   PKG_CHECK_MODULES([CHECK],
+      [check >= 0.9.5],
+      [dummy="yes"],
+      [_efl_enable_tests="no"])
+fi
+
+AM_CONDITIONAL(EFL_ENABLE_TESTS, test "x${_efl_enable_tests}" = "xyes")
+
+AS_IF([test "x$_efl_enable_tests" = "xyes"], [$1], [$2])
+])
+
+dnl End of efl_tests.m4
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644 (file)
index 0000000..770fcb6
--- /dev/null
@@ -0,0 +1,2 @@
+cs de el fr it
+
diff --git a/po/Makevars b/po/Makevars
new file mode 100644 (file)
index 0000000..22837ab
--- /dev/null
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --from-code=UTF-8 --foreign-user
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Enlightenment development team
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = enlightenment-devel@lists.sourceforge.net
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644 (file)
index 0000000..5014aa2
--- /dev/null
@@ -0,0 +1 @@
+src/lib/ecore/ecore_getopt.c
diff --git a/po/cs.po b/po/cs.po
new file mode 100644 (file)
index 0000000..50b1ff0
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,170 @@
+# ecore czech translation
+# quaker66@gmail.com
+msgid ""
+msgstr ""
+"Project-Id-Version: ecore\n"
+"Report-Msgid-Bugs-To: enlightenment-devel@lists.sourceforge.net\n"
+"POT-Creation-Date: 2010-03-08 09:04+0100\n"
+"PO-Revision-Date: 2009-10-27 19:35+0100\n"
+"Last-Translator: quaker66 <quaker66@gmail.com>\n"
+"Language-Team: cs <quaker66@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/lib/ecore/ecore_getopt.c:74
+msgid "Version:"
+msgstr "Verze:"
+
+#: src/lib/ecore/ecore_getopt.c:82
+msgid "Usage:"
+msgstr "Použití:"
+
+#: src/lib/ecore/ecore_getopt.c:87
+#, c-format
+msgid "%s [options]\n"
+msgstr "%s [volby]\n"
+
+#: src/lib/ecore/ecore_getopt.c:235
+msgid "Copyright:"
+msgstr "Copyright:"
+
+#: src/lib/ecore/ecore_getopt.c:246
+msgid "License:"
+msgstr "Licence:"
+
+#: src/lib/ecore/ecore_getopt.c:398
+msgid "Type: "
+msgstr "Typ: "
+
+#: src/lib/ecore/ecore_getopt.c:465
+msgid "Default: "
+msgstr "Výchozí: "
+
+#: src/lib/ecore/ecore_getopt.c:488
+msgid "Choices: "
+msgstr "Možnosti: "
+
+#: src/lib/ecore/ecore_getopt.c:585
+msgid "Options:\n"
+msgstr "Volby:\n"
+
+#: src/lib/ecore/ecore_getopt.c:704
+#, c-format
+msgid "ERROR: unknown option --%s.\n"
+msgstr "CHYBA: neznámá volba --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:706
+#, c-format
+msgid "ERROR: unknown option -%c.\n"
+msgstr "CHYBA: neznámá volba -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:762
+msgid "ERROR: "
+msgstr "CHYBA: "
+
+#: src/lib/ecore/ecore_getopt.c:839 src/lib/ecore/ecore_getopt.c:955
+#: src/lib/ecore/ecore_getopt.c:968 src/lib/ecore/ecore_getopt.c:980
+#: src/lib/ecore/ecore_getopt.c:994 src/lib/ecore/ecore_getopt.c:1038
+#: src/lib/ecore/ecore_getopt.c:1147 src/lib/ecore/ecore_getopt.c:1184
+msgid "value has no pointer set.\n"
+msgstr "hodnota nemá nastaven pointer.\n"
+
+#: src/lib/ecore/ecore_getopt.c:868 src/lib/ecore/ecore_getopt.c:1058
+#, c-format
+msgid "unknown boolean value %s.\n"
+msgstr "neznámá boolean hodnota %s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:912 src/lib/ecore/ecore_getopt.c:1138
+#, c-format
+msgid "invalid number format %s\n"
+msgstr "neznámý číselný formát %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1007
+#, c-format
+msgid "invalid choice \"%s\". Valid values are: "
+msgstr "neznámá volba \"%s\". Možné hodnoty jsou: "
+
+#: src/lib/ecore/ecore_getopt.c:1032
+msgid "missing parameter to append.\n"
+msgstr "chybějící parametr k připojení.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1128
+msgid "could not parse value.\n"
+msgstr "nemůžu parsovat hodnotu.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1177
+msgid "missing parameter.\n"
+msgstr "chybějící parametr.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1191
+msgid "missing callback function!\n"
+msgstr "chybějící callback funkce!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1214
+msgid "no version was defined.\n"
+msgstr "nebyla definována verze.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1228
+msgid "no copyright was defined.\n"
+msgstr "nebyl definován copyright.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1242
+msgid "no license was defined.\n"
+msgstr "nebyla definována licence.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1296
+#, c-format
+msgid "ERROR: unknown option --%s, ignored.\n"
+msgstr "CHYBA: neznámá volba --%s, ignoruji.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1329
+#, c-format
+msgid "ERROR: option --%s requires an argument!\n"
+msgstr "CHYBA: volba --%s vyžaduje argument!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1365
+#, c-format
+msgid "ERROR: unknown option -%c, ignored.\n"
+msgstr "CHYBA: neznámá volba -%c, ignoruji.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1403
+#, c-format
+msgid "ERROR: option -%c requires an argument!\n"
+msgstr "CHYBA: volba -%c vyžaduje argument!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1606
+msgid "ERROR: no parser provided.\n"
+msgstr "CHYBA: nebyl poskytnut parser.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1611
+msgid "ERROR: no values provided.\n"
+msgstr "CHYBA: nebyly poskytnuty hodnoty.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1620
+msgid "ERROR: no arguments provided.\n"
+msgstr "CHYBA: nebyly poskytnuty argumenty.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1646
+msgid "ERROR: invalid options found."
+msgstr "CHYBA: nalezeny neplatné volby."
+
+#: src/lib/ecore/ecore_getopt.c:1652
+#, c-format
+msgid " See --%s.\n"
+msgstr " viz. --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1654
+#, c-format
+msgid " See -%c.\n"
+msgstr " viz. -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1691
+#, c-format
+msgid "ERROR: incorrect geometry value '%s'\n"
+msgstr "CHYBA: neplatná hodnota geometrie '%s'\n"
+
+#: src/lib/ecore/ecore_getopt.c:1714
+#, c-format
+msgid "ERROR: incorrect size value '%s'\n"
+msgstr "CHYBA: neplatná hodnota velikosti '%s'\n"
diff --git a/po/de.po b/po/de.po
new file mode 100644 (file)
index 0000000..0920a04
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,173 @@
+# Translation of ecore to German
+# Copyright (C) 2000 Carsten Haitzler and others.
+# This file is distributed under the same license as the ecore package.
+# Chris Leick <c.leick@vollbio.de>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ecore 0.9.9.063-2\n"
+"Report-Msgid-Bugs-To: enlightenment-devel@lists.sourceforge.net\n"
+"POT-Creation-Date: 2010-03-08 09:04+0100\n"
+"PO-Revision-Date: 2010-01-03 21:52+GMT\n"
+"Last-Translator: Chris Leick <c.leick@vollbio.de>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/lib/ecore/ecore_getopt.c:74
+msgid "Version:"
+msgstr "Version:"
+
+#: src/lib/ecore/ecore_getopt.c:82
+msgid "Usage:"
+msgstr "Aufruf:"
+
+#: src/lib/ecore/ecore_getopt.c:87
+#, c-format
+msgid "%s [options]\n"
+msgstr "%s [Optionen]\n"
+
+#: src/lib/ecore/ecore_getopt.c:235
+msgid "Copyright:"
+msgstr "Copyright:"
+
+#: src/lib/ecore/ecore_getopt.c:246
+msgid "License:"
+msgstr "Lizenz:"
+
+#: src/lib/ecore/ecore_getopt.c:398
+msgid "Type: "
+msgstr "Typ: "
+
+#: src/lib/ecore/ecore_getopt.c:465
+msgid "Default: "
+msgstr "Vorgabe: "
+
+#: src/lib/ecore/ecore_getopt.c:488
+msgid "Choices: "
+msgstr "Auswahlen: "
+
+#: src/lib/ecore/ecore_getopt.c:585
+msgid "Options:\n"
+msgstr "Optionen:\n"
+
+#: src/lib/ecore/ecore_getopt.c:704
+#, c-format
+msgid "ERROR: unknown option --%s.\n"
+msgstr "FEHLER: Unbekannte Option --%s\n"
+
+#: src/lib/ecore/ecore_getopt.c:706
+#, c-format
+msgid "ERROR: unknown option -%c.\n"
+msgstr "FEHLER: Unbekannte Option -%c\n"
+
+#: src/lib/ecore/ecore_getopt.c:762
+msgid "ERROR: "
+msgstr "FEHLER: "
+
+#: src/lib/ecore/ecore_getopt.c:839 src/lib/ecore/ecore_getopt.c:955
+#: src/lib/ecore/ecore_getopt.c:968 src/lib/ecore/ecore_getopt.c:980
+#: src/lib/ecore/ecore_getopt.c:994 src/lib/ecore/ecore_getopt.c:1038
+#: src/lib/ecore/ecore_getopt.c:1147 src/lib/ecore/ecore_getopt.c:1184
+msgid "value has no pointer set.\n"
+msgstr "kein Zeiger auf Wert gesetzt\n"
+
+#: src/lib/ecore/ecore_getopt.c:868 src/lib/ecore/ecore_getopt.c:1058
+#, c-format
+msgid "unknown boolean value %s.\n"
+msgstr "unbekannter boolescher Wert %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:912 src/lib/ecore/ecore_getopt.c:1138
+#, c-format
+msgid "invalid number format %s\n"
+msgstr "ungültiges Zahlenformat %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1007
+#, c-format
+msgid "invalid choice \"%s\". Valid values are: "
+msgstr "ungültige Auswahl »%s«. Gültige Werte sind: "
+
+#: src/lib/ecore/ecore_getopt.c:1032
+msgid "missing parameter to append.\n"
+msgstr "fehlender Parameter zum Anhängen\n"
+
+#: src/lib/ecore/ecore_getopt.c:1128
+msgid "could not parse value.\n"
+msgstr "Wert kann nicht ausgewertet werden\n"
+
+#: src/lib/ecore/ecore_getopt.c:1177
+msgid "missing parameter.\n"
+msgstr "fehlender Parameter\n"
+
+#: src/lib/ecore/ecore_getopt.c:1191
+msgid "missing callback function!\n"
+msgstr "fehlende Rückruffunktion!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1214
+msgid "no version was defined.\n"
+msgstr "es wurde keine Version definiert.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1228
+msgid "no copyright was defined.\n"
+msgstr "es wurde kein Copyright definiert.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1242
+msgid "no license was defined.\n"
+msgstr "es wurde keine Lizenz definiert.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1296
+#, c-format
+msgid "ERROR: unknown option --%s, ignored.\n"
+msgstr "FEHLER: Unbekannte Option --%s, ignoriert\n"
+
+#: src/lib/ecore/ecore_getopt.c:1329
+#, c-format
+msgid "ERROR: option --%s requires an argument!\n"
+msgstr "FEHLER: Option --%s benötigt ein Argument!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1365
+#, c-format
+msgid "ERROR: unknown option -%c, ignored.\n"
+msgstr "FEHLER: Unbekannte Option -%c, ignoriert\n"
+
+#: src/lib/ecore/ecore_getopt.c:1403
+#, c-format
+msgid "ERROR: option -%c requires an argument!\n"
+msgstr "FEHLER: Option -%c benötigt ein Argument!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1606
+msgid "ERROR: no parser provided.\n"
+msgstr "FEHLER: Kein Parser bereitgestellt\n"
+
+#: src/lib/ecore/ecore_getopt.c:1611
+msgid "ERROR: no values provided.\n"
+msgstr "FEHLER: Keine Werte bereitgestellt\n"
+
+#: src/lib/ecore/ecore_getopt.c:1620
+msgid "ERROR: no arguments provided.\n"
+msgstr "FEHLER: Keine Argumente bereitgestellt\n"
+
+#: src/lib/ecore/ecore_getopt.c:1646
+msgid "ERROR: invalid options found."
+msgstr "FEHLER: Ungültige Optionen gefunden"
+
+#: src/lib/ecore/ecore_getopt.c:1652
+#, c-format
+msgid " See --%s.\n"
+msgstr " Siehe --%s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1654
+#, c-format
+msgid " See -%c.\n"
+msgstr " Siehe -%c\n"
+
+#: src/lib/ecore/ecore_getopt.c:1691
+#, c-format
+msgid "ERROR: incorrect geometry value '%s'\n"
+msgstr "FEHLER: Falscher Geometriewert »%s«\n"
+
+#: src/lib/ecore/ecore_getopt.c:1714
+#, c-format
+msgid "ERROR: incorrect size value '%s'\n"
+msgstr "FEHLER: Falscher Größenwert »%s«\n"
diff --git a/po/el.po b/po/el.po
new file mode 100644 (file)
index 0000000..6e455b8
--- /dev/null
+++ b/po/el.po
@@ -0,0 +1,203 @@
+# Greek translation for Ecore.
+# This file is put in the public domain.
+# ragecryx <ragecryx@yahoo.gr>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Ecore\n"
+"Report-Msgid-Bugs-To: enlightenment-devel@lists.sourceforge.net\n"
+"POT-Creation-Date: 2010-03-08 09:04+0100\n"
+"PO-Revision-Date: 2009-12-15 00:56+0200\n"
+"Last-Translator: Giorgos Koutsikos <ragecryx@yahoo.gr>\n"
+"Language-Team: Greek\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/lib/ecore/ecore_getopt.c:74
+msgid "Version:"
+msgstr "Έκδοση:"
+
+#: src/lib/ecore/ecore_getopt.c:82
+msgid "Usage:"
+msgstr "Χρήση:"
+
+#: src/lib/ecore/ecore_getopt.c:87
+#, c-format
+msgid "%s [options]\n"
+msgstr "%s [επιλογές]\n"
+
+#: src/lib/ecore/ecore_getopt.c:235
+msgid "Copyright:"
+msgstr "Πνευματικά δικαιώματα:"
+
+#: src/lib/ecore/ecore_getopt.c:246
+msgid "License:"
+msgstr "Άδεια:"
+
+#: src/lib/ecore/ecore_getopt.c:398
+msgid "Type: "
+msgstr "Τύπος:"
+
+#: src/lib/ecore/ecore_getopt.c:465
+msgid "Default: "
+msgstr "Προκαθορισμένο:"
+
+#: src/lib/ecore/ecore_getopt.c:488
+msgid "Choices: "
+msgstr "Επιλογές:"
+
+#: src/lib/ecore/ecore_getopt.c:585
+msgid "Options:\n"
+msgstr "Επιλογές:\n"
+
+#: src/lib/ecore/ecore_getopt.c:704
+#, c-format
+msgid "ERROR: unknown option --%s.\n"
+msgstr "ΣΦΑΛΜΑ: άγνωστη παράμετρος --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:706
+#, c-format
+msgid "ERROR: unknown option -%c.\n"
+msgstr "ΣΦΑΛΜΑ: άγνωστη παράμετρος -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:762
+msgid "ERROR: "
+msgstr "ΣΦΑΛΜΑ:"
+
+#: src/lib/ecore/ecore_getopt.c:839 src/lib/ecore/ecore_getopt.c:955
+#: src/lib/ecore/ecore_getopt.c:968 src/lib/ecore/ecore_getopt.c:980
+#: src/lib/ecore/ecore_getopt.c:994 src/lib/ecore/ecore_getopt.c:1038
+#: src/lib/ecore/ecore_getopt.c:1147 src/lib/ecore/ecore_getopt.c:1184
+msgid "value has no pointer set.\n"
+msgstr "η τιμή δεν έχει δείκτη ορισμένο.\n"
+
+#: src/lib/ecore/ecore_getopt.c:868 src/lib/ecore/ecore_getopt.c:1058
+#, c-format
+msgid "unknown boolean value %s.\n"
+msgstr "άγνωστη τιμή boolean %s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:912 src/lib/ecore/ecore_getopt.c:1138
+#, c-format
+msgid "invalid number format %s\n"
+msgstr "άγνωστη μορφή αριθμού %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1007
+#, c-format
+msgid "invalid choice \"%s\". Valid values are: "
+msgstr "μη-έγκυρη επιλογή \"%s\". Οι τιμές είναι: "
+
+#: src/lib/ecore/ecore_getopt.c:1032
+msgid "missing parameter to append.\n"
+msgstr "ελλιπής παράμετρος προς επισύναψη.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1128
+msgid "could not parse value.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1177
+msgid "missing parameter.\n"
+msgstr "ελλιπής παράμετρος.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1191
+msgid "missing callback function!\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1214
+msgid "no version was defined.\n"
+msgstr "δεν έχει οριστεί έκδοση.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1228
+msgid "no copyright was defined.\n"
+msgstr "δεν έχουν οριστεί πνευματικά δικαιώματα.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1242
+msgid "no license was defined.\n"
+msgstr "δεν έχει οριστεί άδεια.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1296
+#, c-format
+msgid "ERROR: unknown option --%s, ignored.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1329
+#, c-format
+msgid "ERROR: option --%s requires an argument!\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1365
+#, c-format
+msgid "ERROR: unknown option -%c, ignored.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1403
+#, c-format
+msgid "ERROR: option -%c requires an argument!\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1606
+msgid "ERROR: no parser provided.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1611
+msgid "ERROR: no values provided.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1620
+msgid "ERROR: no arguments provided.\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1646
+msgid "ERROR: invalid options found."
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1652
+#, c-format
+msgid " See --%s.\n"
+msgstr " Δες --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1654
+#, c-format
+msgid " See -%c.\n"
+msgstr " Δες -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1691
+#, c-format
+msgid "ERROR: incorrect geometry value '%s'\n"
+msgstr ""
+
+#: src/lib/ecore/ecore_getopt.c:1714
+#, c-format
+msgid "ERROR: incorrect size value '%s'\n"
+msgstr ""
+
+#~ msgid ""
+#~ "\n"
+#~ "   "
+#~ msgstr ""
+#~ "\n"
+#~ "   "
+
+#~ msgid "true"
+#~ msgstr "true"
+
+#~ msgid "false"
+#~ msgstr "false"
+
+#~ msgid "f"
+#~ msgstr "f"
+
+#~ msgid "no"
+#~ msgstr "no"
+
+#~ msgid "off"
+#~ msgstr "off"
+
+#~ msgid "t"
+#~ msgstr "t"
+
+#~ msgid "yes"
+#~ msgstr "yes"
+
+#~ msgid "on"
+#~ msgstr "on"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644 (file)
index 0000000..d9db977
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,206 @@
+# French translation for Ecore.
+# This file is put in the public domain.
+# batden <batden@orange.fr>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Ecore\n"
+"Report-Msgid-Bugs-To: enlightenment-devel@lists.sourceforge.net\n"
+"POT-Creation-Date: 2010-03-08 09:04+0100\n"
+"PO-Revision-Date: 2010-03-13 14:04+0400\n"
+"Last-Translator: batden <batden@orange.fr>\n"
+"Language-Team: Enlightenment French Team <pourunmondesansgourou@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+"X-Poedit-Language: French\n"
+"X-Poedit-Country: FRANCE\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#: src/lib/ecore/ecore_getopt.c:74
+msgid "Version:"
+msgstr "Version :"
+
+#: src/lib/ecore/ecore_getopt.c:82
+msgid "Usage:"
+msgstr "Usage :"
+
+#: src/lib/ecore/ecore_getopt.c:87
+#, c-format
+msgid "%s [options]\n"
+msgstr "%s [options]\n"
+
+#: src/lib/ecore/ecore_getopt.c:235
+msgid "Copyright:"
+msgstr "Copyright :"
+
+#: src/lib/ecore/ecore_getopt.c:246
+msgid "License:"
+msgstr "Licence :"
+
+#: src/lib/ecore/ecore_getopt.c:398
+msgid "Type: "
+msgstr "Type : "
+
+#: src/lib/ecore/ecore_getopt.c:465
+msgid "Default: "
+msgstr "Par défaut :"
+
+#: src/lib/ecore/ecore_getopt.c:488
+msgid "Choices: "
+msgstr "Choix :"
+
+#: src/lib/ecore/ecore_getopt.c:585
+msgid "Options:\n"
+msgstr "Options :\n"
+
+#: src/lib/ecore/ecore_getopt.c:704
+#, c-format
+msgid "ERROR: unknown option --%s.\n"
+msgstr "ERREUR : option inconnue --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:706
+#, c-format
+msgid "ERROR: unknown option -%c.\n"
+msgstr "ERREUR : option inconnue -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:762
+msgid "ERROR: "
+msgstr "ERREUR :"
+
+#: src/lib/ecore/ecore_getopt.c:839
+#: src/lib/ecore/ecore_getopt.c:955
+#: src/lib/ecore/ecore_getopt.c:968
+#: src/lib/ecore/ecore_getopt.c:980
+#: src/lib/ecore/ecore_getopt.c:994
+#: src/lib/ecore/ecore_getopt.c:1038
+#: src/lib/ecore/ecore_getopt.c:1147
+#: src/lib/ecore/ecore_getopt.c:1184
+msgid "value has no pointer set.\n"
+msgstr "la valeur n'a aucun pointeur défini.\n"
+
+#: src/lib/ecore/ecore_getopt.c:868
+#: src/lib/ecore/ecore_getopt.c:1058
+#, c-format
+msgid "unknown boolean value %s.\n"
+msgstr "valeur booléenne inconnue %s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:912
+#: src/lib/ecore/ecore_getopt.c:1138
+#, c-format
+msgid "invalid number format %s\n"
+msgstr "format du nombre non valide %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1007
+#, c-format
+msgid "invalid choice \"%s\". Valid values are: "
+msgstr "choix non valide \"%s\". Les valeurs valides sont : "
+
+#: src/lib/ecore/ecore_getopt.c:1032
+msgid "missing parameter to append.\n"
+msgstr "paramètre manquant à ajouter.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1128
+msgid "could not parse value.\n"
+msgstr "analyse de la valeur impossible.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1177
+msgid "missing parameter.\n"
+msgstr "paramètre manquant.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1191
+msgid "missing callback function!\n"
+msgstr "fonction de rappel manquante !\n"
+
+#: src/lib/ecore/ecore_getopt.c:1214
+msgid "no version was defined.\n"
+msgstr "aucune version n'est définie.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1228
+msgid "no copyright was defined.\n"
+msgstr "aucun copyright n'est défini.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1242
+msgid "no license was defined.\n"
+msgstr "aucune licence n'est définie.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1296
+#, c-format
+msgid "ERROR: unknown option --%s, ignored.\n"
+msgstr "ERREUR : option inconnue --%s, non prise en compte.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1329
+#, c-format
+msgid "ERROR: option --%s requires an argument!\n"
+msgstr "ERREUR : l'option --%s requiert un argument !\n"
+
+#: src/lib/ecore/ecore_getopt.c:1365
+#, c-format
+msgid "ERROR: unknown option -%c, ignored.\n"
+msgstr "ERREUR : option inconnue -%c, non prise en compte.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1403
+#, c-format
+msgid "ERROR: option -%c requires an argument!\n"
+msgstr "ERREUR : l'option -%c requiert un argument !\n"
+
+#: src/lib/ecore/ecore_getopt.c:1606
+msgid "ERROR: no parser provided.\n"
+msgstr "ERREUR : aucun analyseur n'est fourni.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1611
+msgid "ERROR: no values provided.\n"
+msgstr "ERREUR : aucune valeur n'est fournie.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1620
+msgid "ERROR: no arguments provided.\n"
+msgstr "ERREUR : aucun argument n'est fourni.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1646
+msgid "ERROR: invalid options found."
+msgstr "ERREUR : options non valides détectées."
+
+#: src/lib/ecore/ecore_getopt.c:1652
+#, c-format
+msgid " See --%s.\n"
+msgstr " Voir --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1654
+#, c-format
+msgid " See -%c.\n"
+msgstr " Voir -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1691
+#, c-format
+msgid "ERROR: incorrect geometry value '%s'\n"
+msgstr "ERREUR : valeur géométrique incorrecte '%s'\n"
+
+#: src/lib/ecore/ecore_getopt.c:1714
+#, c-format
+msgid "ERROR: incorrect size value '%s'\n"
+msgstr "ERREUR : valeur de taille incorrecte '%s'\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "   "
+#~ msgstr ""
+#~ "\n"
+#~ "   "
+#~ msgid "true"
+#~ msgstr "true"
+#~ msgid "false"
+#~ msgstr "false"
+#~ msgid "f"
+#~ msgstr "f"
+#~ msgid "no"
+#~ msgstr "no"
+#~ msgid "off"
+#~ msgstr "off"
+#~ msgid "t"
+#~ msgstr "t"
+#~ msgid "yes"
+#~ msgstr "yes"
+#~ msgid "on"
+#~ msgstr "on"
+
diff --git a/po/it.po b/po/it.po
new file mode 100644 (file)
index 0000000..61ec74b
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,203 @@
+# Italian translation for Ecore.
+# This file is put in the public domain.
+# Massimo Maiurana <maiurana@gmail.com>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Ecore\n"
+"Report-Msgid-Bugs-To: enlightenment-devel@lists.sourceforge.net\n"
+"POT-Creation-Date: 2010-03-08 09:04+0100\n"
+"PO-Revision-Date: 2009-10-27 19:36+0100\n"
+"Last-Translator: quaker66 <quaker66@gmail.com>\n"
+"Language-Team: none\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/lib/ecore/ecore_getopt.c:74
+msgid "Version:"
+msgstr "Versione:"
+
+#: src/lib/ecore/ecore_getopt.c:82
+msgid "Usage:"
+msgstr "Uso:"
+
+#: src/lib/ecore/ecore_getopt.c:87
+#, c-format
+msgid "%s [options]\n"
+msgstr "%s [opzioni]\n"
+
+#: src/lib/ecore/ecore_getopt.c:235
+msgid "Copyright:"
+msgstr "Copyright:"
+
+#: src/lib/ecore/ecore_getopt.c:246
+msgid "License:"
+msgstr "Licenza:"
+
+#: src/lib/ecore/ecore_getopt.c:398
+msgid "Type: "
+msgstr "Tipo: "
+
+#: src/lib/ecore/ecore_getopt.c:465
+msgid "Default: "
+msgstr "Predefinito:"
+
+#: src/lib/ecore/ecore_getopt.c:488
+msgid "Choices: "
+msgstr "Scelte:"
+
+#: src/lib/ecore/ecore_getopt.c:585
+msgid "Options:\n"
+msgstr "Opzioni:\n"
+
+#: src/lib/ecore/ecore_getopt.c:704
+#, c-format
+msgid "ERROR: unknown option --%s.\n"
+msgstr "ERRORE: opzione sconosciuta --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:706
+#, c-format
+msgid "ERROR: unknown option -%c.\n"
+msgstr "ERRORE: opzione sconosciuta -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:762
+msgid "ERROR: "
+msgstr "ERRORE:"
+
+#: src/lib/ecore/ecore_getopt.c:839 src/lib/ecore/ecore_getopt.c:955
+#: src/lib/ecore/ecore_getopt.c:968 src/lib/ecore/ecore_getopt.c:980
+#: src/lib/ecore/ecore_getopt.c:994 src/lib/ecore/ecore_getopt.c:1038
+#: src/lib/ecore/ecore_getopt.c:1147 src/lib/ecore/ecore_getopt.c:1184
+msgid "value has no pointer set.\n"
+msgstr "il valore non ha puntatori impostati.\n"
+
+#: src/lib/ecore/ecore_getopt.c:868 src/lib/ecore/ecore_getopt.c:1058
+#, c-format
+msgid "unknown boolean value %s.\n"
+msgstr "valore booleano sconosciuto %s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:912 src/lib/ecore/ecore_getopt.c:1138
+#, c-format
+msgid "invalid number format %s\n"
+msgstr "formato numero non valido %s\n"
+
+#: src/lib/ecore/ecore_getopt.c:1007
+#, c-format
+msgid "invalid choice \"%s\". Valid values are: "
+msgstr "scelta non valida \"%s\". I valori ammessi sono: "
+
+#: src/lib/ecore/ecore_getopt.c:1032
+msgid "missing parameter to append.\n"
+msgstr "parametro da appendere mancante.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1128
+msgid "could not parse value.\n"
+msgstr "impossibile il parsing del valore.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1177
+msgid "missing parameter.\n"
+msgstr "parametro mancante.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1191
+msgid "missing callback function!\n"
+msgstr "funzione callback mancante!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1214
+msgid "no version was defined.\n"
+msgstr "nessuna versione definita.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1228
+msgid "no copyright was defined.\n"
+msgstr "nessun copyright definito.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1242
+msgid "no license was defined.\n"
+msgstr "nessuna licenza definita.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1296
+#, c-format
+msgid "ERROR: unknown option --%s, ignored.\n"
+msgstr "ERRORE: opzione sconosciuta --%s, ignorata.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1329
+#, c-format
+msgid "ERROR: option --%s requires an argument!\n"
+msgstr "ERRORE: l'opzione --%s richiede un argomento!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1365
+#, c-format
+msgid "ERROR: unknown option -%c, ignored.\n"
+msgstr "ERRORE: opzione sconosciuta -%c, ignorata.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1403
+#, c-format
+msgid "ERROR: option -%c requires an argument!\n"
+msgstr "ERRORE: l'opzione -%c richiede un argomento!\n"
+
+#: src/lib/ecore/ecore_getopt.c:1606
+msgid "ERROR: no parser provided.\n"
+msgstr "ERRORE: nessun parser fornito.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1611
+msgid "ERROR: no values provided.\n"
+msgstr "ERRORE: nessun valore fornito.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1620
+msgid "ERROR: no arguments provided.\n"
+msgstr "ERRORE: nessun argomento fornito.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1646
+msgid "ERROR: invalid options found."
+msgstr "ERRORE: trovate opzioni non valide."
+
+#: src/lib/ecore/ecore_getopt.c:1652
+#, c-format
+msgid " See --%s.\n"
+msgstr " Vedere --%s.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1654
+#, c-format
+msgid " See -%c.\n"
+msgstr " Vedere -%c.\n"
+
+#: src/lib/ecore/ecore_getopt.c:1691
+#, c-format
+msgid "ERROR: incorrect geometry value '%s'\n"
+msgstr "ERRORE: valore geometrico non corretto '%s'\n"
+
+#: src/lib/ecore/ecore_getopt.c:1714
+#, c-format
+msgid "ERROR: incorrect size value '%s'\n"
+msgstr "ERRORE: valore dimensione non corretto '%s'\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "   "
+#~ msgstr ""
+#~ "\n"
+#~ "   "
+
+#~ msgid "true"
+#~ msgstr "vero"
+
+#~ msgid "false"
+#~ msgstr "falso"
+
+#~ msgid "f"
+#~ msgstr "f"
+
+#~ msgid "no"
+#~ msgstr "no"
+
+#~ msgid "off"
+#~ msgstr "off"
+
+#~ msgid "t"
+#~ msgstr "t"
+
+#~ msgid "yes"
+#~ msgstr "sì"
+
+#~ msgid "on"
+#~ msgstr "on"
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..a6fc38f
--- /dev/null
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = lib bin tests
diff --git a/src/bin/.cvsignore b/src/bin/.cvsignore
new file mode 100644 (file)
index 0000000..79fccac
--- /dev/null
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+ecore_config
+ecore_evas_test
+ecore_test
+ecore_dbus_test
+ecore_dbus_hal_test
+ecore_dbus_receiver_test
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644 (file)
index 0000000..bf59b69
--- /dev/null
@@ -0,0 +1,37 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_CONFIG
+ECORE_CONFIG_PROG = ecore_config
+ECORE_CONFIG_LIB = $(top_builddir)/src/lib/ecore_config/libecore_config.la
+else
+ECORE_CONFIG_PROG =
+ECORE_CONFIG_LIB =
+endif
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_config \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_config \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+@EINA_CFLAGS@ \
+@EET_CFLAGS@
+
+bin_PROGRAMS = $(ECORE_CONFIG_PROG)
+
+ecore_config_SOURCES = \
+ecore_config.c
+
+ecore_config_LDADD = \
+$(ECORE_CONFIG_LIB) \
+$(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la \
+$(top_builddir)/src/lib/ecore/libecore.la
+
+ecore_config_DEPENDENCIES = \
+$(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(ECORE_CONFIG_LIB)
diff --git a/src/bin/ecore_config.c b/src/bin/ecore_config.c
new file mode 100644 (file)
index 0000000..8bf2988
--- /dev/null
@@ -0,0 +1,324 @@
+#include "config.h"
+#include "Ecore.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef BUILD_ECORE_CONFIG
+#include <unistd.h>
+#include <getopt.h>
+#include <Eet.h>
+#include "Ecore_Config.h"
+#include "ecore_config_private.h"
+
+// strcmp for paths - for sorting folders before files
+static int
+pathcmp(const char *s1, const char *s2)
+{
+   char *s1d, *s2d;
+
+   // strip common part of paths
+   while(*s1 && *s2 && *s1 == *s2)
+     {
+       s1++;
+       s2++;
+     }
+
+   // handle /foo/bar/baz <> /foo/bar_baz properly
+   if (*s1 == '/' && *s2 != '/') return -1;
+   if (*s1 != '/' && *s2 == '/') return  1;
+
+   // skip leading /
+   if (*s1 == '/') s1++;
+   if (*s2 == '/') s2++;
+
+   // order folders before files
+   s1d = strchr(s1, '/');
+   s2d = strchr(s2, '/');
+   if (s1d != NULL && s2d == NULL) return -1;
+   if (s1d == NULL && s2d != NULL) return  1;
+
+   return strcmp(s1, s2);
+}
+
+static int
+del(const char *key)
+{
+   Ecore_Config_Prop *e;
+   e = ecore_config_get(key);
+   if(e == NULL) return -1;
+
+   ecore_config_dst(e);
+   return 0;
+}
+
+static int
+get(const char *key)
+{
+   Ecore_Config_Prop *e;
+   char *temp = NULL;
+
+   if (!(e = ecore_config_get(key)))
+     {
+       EINA_LOG_ERR("No such property");
+       return -1;
+     }
+     
+   printf("%-10s", ecore_config_type_get(e));
+
+   switch (e->type)
+     {
+       case ECORE_CONFIG_NIL:
+          printf("\n");
+          break;
+       case ECORE_CONFIG_INT:
+          printf("%ld\n", ecore_config_int_get(key));
+          break;
+       case ECORE_CONFIG_BLN:
+          printf("%d\n",  ecore_config_boolean_get(key));
+          break;
+       case ECORE_CONFIG_FLT:
+          printf("%lf\n", ecore_config_float_get(key));
+          break;
+       case ECORE_CONFIG_STR:
+          temp = ecore_config_string_get(key);
+          break;
+       case ECORE_CONFIG_RGB:
+          temp = ecore_config_argbstr_get(key);
+          break;
+       case ECORE_CONFIG_THM:
+          temp = ecore_config_theme_get(key);
+          break;
+       default:
+          EINA_LOG_ERR("Property has unrecognized type");
+          return -1;
+     }
+   if(temp)
+     {
+       printf("\"%s\"\n", temp);
+       free(temp);
+     }
+   return 0;
+}
+
+static int
+list(const char *file)
+{
+   Ecore_Config_Prop *e;
+   Eina_List *keys = NULL;
+   char *key;
+
+   e = __ecore_config_bundle_local->data;
+
+   do
+     {
+       // don't show system settings
+       if( !(e->flags & ECORE_CONFIG_FLAG_SYSTEM) )
+          keys = eina_list_append(keys, e->key);
+     }
+   while((e = e->next));
+   keys = eina_list_sort(keys, -1, EINA_COMPARE_CB(pathcmp));
+
+   EINA_LIST_FREE(keys, key)
+     {
+       printf("%-28s\t", key);
+       get(key);
+     }
+
+   return 0;
+}
+
+static void
+usage_and_exit(const char *prog, int ret, const char *msg)
+{
+   if (msg) fprintf(stderr, "%s\n\n", msg);
+   fprintf(stderr, "Usage: %s <options> <command>\n", prog);
+   fprintf(stderr, "Modify ecore_config files\n\n");
+   fprintf(stderr, "Options:\n");
+   fprintf(stderr, "  -c, --file=FILE config file\n");
+   fprintf(stderr, "  -k, --key=KEY   must be given for all commands except -a\n\n");
+   fprintf(stderr, "Commands:\n");
+   fprintf(stderr, "  -a, --list         get all keys\n");
+   fprintf(stderr, "  -g, --get          get key\n");
+   fprintf(stderr, "  -d, --del          delete key\n");
+   fprintf(stderr, "  -b, --bool=VALUE   set boolean\n");
+   fprintf(stderr, "  -f, --float=VALUE  set float\n");
+   fprintf(stderr, "  -i, --int=VALUE    set integer\n");
+   fprintf(stderr, "  -r, --rgb=VALUE    set RGBA\n");
+   fprintf(stderr, "  -s, --string=VALUE set string\n");
+   fprintf(stderr, "  -t, --theme=VALUE  set theme\n\n");
+   exit(ret);
+}
+
+int
+main(int argc, char * const argv[])
+{
+   char *prog, *file, *key;
+   void *value = (void *)NULL;
+   char cmd = 's';
+   int type = -1;
+   int ret = 0;
+   long i;
+   float f;
+   
+   file = key = prog = NULL;
+   eina_init();
+   prog = strdup(argv[0]);
+
+   if(argc < 4)
+     usage_and_exit(prog, 2, NULL);
+
+   while(1)
+     {
+       static struct option long_options[] = {
+          {"file",   1, 0, 'c'},
+          {"list",   0, 0, 'a'},
+          {"get",    0, 0, 'g'},
+          {"del",    0, 0, 'd'},
+          {"bool",   1, 0, 'b'},
+          {"float",  1, 0, 'f'},
+          {"int",    1, 0, 'i'},
+          {"rgb",    1, 0, 'r'},
+          {"string", 1, 0, 's'},
+          {"theme",  1, 0, 't'},
+          {"key",    1, 0, 'k'},
+          {0, 0, 0, 0}
+       };
+
+       ret = getopt_long(argc, argv, "c:agdb:f:i:r:s:t:k:", long_options, NULL);
+       if(ret == -1)
+          break;
+
+       switch(ret)
+          {
+            case 'k':
+               key = strdup(optarg);
+               break;
+            case 'n':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_NIL;
+               value = NULL;
+               break;
+            case 'b':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_BLN;
+               i = atoi(optarg);
+               value = &i;
+               break;
+            case 'i':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_INT;
+               i = atoi(optarg);
+               value = &i;
+               break;
+            case 'f':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_FLT;
+               f = atof(optarg);
+               value = &f;
+               break;
+            case 'r':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_RGB;
+               i = (long) strtoul( (*optarg == '#') ? (optarg + 1) : optarg, NULL, 16 );
+               value = &i;
+               break;
+            case 's':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_STR;
+               value = strdup(optarg);
+               break;
+            case 't':
+               if(value)
+                  usage_and_exit(prog, 2, "too many commands");
+               type = ECORE_CONFIG_THM;
+               value = strdup(optarg);
+               break;
+            case 'c':
+               if(file)
+                  free(file);
+               file = strdup(optarg);
+               break;
+            case '?':
+            case ':':
+               return 1;
+            default:
+               cmd = ret;
+               break;
+          }
+     }
+
+   if(cmd == 's' && type == -1)
+     usage_and_exit(prog, 2, "You need to specify a command!");
+
+   if(cmd != 'a' && key == NULL)
+     usage_and_exit(prog, 2, "You need to specify key!");
+   
+   if(ecore_config_init("econfig") != ECORE_CONFIG_ERR_SUCC)
+     {
+       EINA_LOG_ERR("Couldn't init ecore_config!");
+       return 1;
+     }
+
+   // Load configuration from file
+   ecore_config_file_load(file);
+
+   ret = 0;
+
+   // Execute command
+   switch (cmd)
+     {
+       case 's':
+          if (ecore_config_typed_set(key, value, type) != ECORE_CONFIG_ERR_SUCC)
+            {
+               fprintf(stderr, "Set failed for %s", key);
+               ret = 1;
+            } else {
+               ecore_config_file_save(file);
+            }
+            get(key); // display value after setting it
+          break;
+       case 'd':
+          if(del(key))
+            {
+               fprintf(stderr, "Delete failed for %s", key);
+               ret = 1;
+            } else {
+               ecore_config_file_save(file);
+            }
+          break;
+       case 'g':
+          if (get(key)) ret = 1;
+          break;
+       case 'a':
+          if (list(file)) ret = 1;
+          break;
+       default:
+          EINA_LOG_ERR("Unhandled command '%c'", cmd);
+     }
+
+   ecore_config_shutdown();
+
+   if(type == ECORE_CONFIG_STR || type == ECORE_CONFIG_THM)
+     free(value);
+
+   if(file)
+     free(file);
+   eina_shutdown();
+   return ret;
+}
+#else
+int
+main(int argc, const char **argv)
+{
+   printf("Ecore_config module not compiled. This program is empty.\n");
+   return -1;
+}
+#endif
diff --git a/src/lib/.cvsignore b/src/lib/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644 (file)
index 0000000..0c00c6a
--- /dev/null
@@ -0,0 +1,20 @@
+## Process this file with automake to produce Makefile.in
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = \
+ecore \
+ecore_input \
+ecore_input_evas \
+ecore_fb \
+ecore_directfb \
+ecore_con \
+ecore_x \
+ecore_win32 \
+ecore_wince \
+ecore_sdl \
+ecore_cocoa \
+ecore_ipc \
+ecore_evas \
+ecore_config \
+ecore_file \
+ecore_imf \
+ecore_imf_evas
diff --git a/src/lib/ecore/.cvsignore b/src/lib/ecore/.cvsignore
new file mode 100644 (file)
index 0000000..78de274
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore.la
diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h
new file mode 100644 (file)
index 0000000..48dea7b
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef _ECORE_H
+#define _ECORE_H
+
+#ifdef _MSC_VER
+# include <Evil.h>
+#endif
+
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file Ecore.h
+ * @brief The file that provides the program utility, main loop and timer
+ *        functions.
+ *
+ * This header provides the Ecore event handling loop.  For more
+ * details, see @ref Ecore_Main_Loop_Group.
+ *
+ * For the main loop to be of any use, you need to be able to add events
+ * and event handlers.  Events for file descriptor events are covered in
+ * @ref Ecore_FD_Handler_Group.
+ *
+ * Time functions are covered in @ref Ecore_Time_Group.
+ *
+ * There is also provision for callbacks for when the loop enters or
+ * exits an idle state. See @ref Idle_Group for more information.
+ *
+ * Functions are also provided for spawning child processes using fork.
+ * See @ref Ecore_Exe_Basic_Group and @ref Ecore_Exe_Signal_Group for
+ * more details.
+ */
+
+#ifdef _WIN32
+# include <winsock2.h>
+#elif (defined (__FreeBSD__) && (__FreeBSD_version >= 420001)) || defined (__OpenBSD__)
+# include <sys/select.h>
+# include <signal.h>
+#else
+# include <sys/time.h>
+# include <signal.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ECORE_CALLBACK_CANCEL 0 /**< Return value to remove a callback */
+#define ECORE_CALLBACK_RENEW 1  /**< Return value to keep a callback */
+
+#define ECORE_EVENT_NONE            0
+#define ECORE_EVENT_SIGNAL_USER     1 /**< User signal event */
+#define ECORE_EVENT_SIGNAL_HUP      2 /**< Hup signal event */
+#define ECORE_EVENT_SIGNAL_EXIT     3 /**< Exit signal event */
+#define ECORE_EVENT_SIGNAL_POWER    4 /**< Power signal event */
+#define ECORE_EVENT_SIGNAL_REALTIME 5 /**< Realtime signal event */
+#define ECORE_EVENT_COUNT           6
+
+#define ECORE_EXE_PRIORITY_INHERIT 9999
+   
+   EAPI extern int ECORE_EXE_EVENT_ADD; /**< A child process has been added */
+   EAPI extern int ECORE_EXE_EVENT_DEL; /**< A child process has been deleted (it exited, naming consistant with the rest of ecore). */
+   EAPI extern int ECORE_EXE_EVENT_DATA; /**< Data from a child process. */
+   EAPI extern int ECORE_EXE_EVENT_ERROR; /**< Errors from a child process. */
+
+   enum _Ecore_Fd_Handler_Flags
+     {
+       ECORE_FD_READ = 1, /**< Fd Read mask */
+       ECORE_FD_WRITE = 2, /**< Fd Write mask */
+       ECORE_FD_ERROR = 4 /**< Fd Error mask */
+     };
+   typedef enum _Ecore_Fd_Handler_Flags Ecore_Fd_Handler_Flags;
+
+   enum _Ecore_Exe_Flags /* flags for executing a child with its stdin and/or stdout piped back */
+     {
+       ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */
+       ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */
+       ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */
+       ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */
+       ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */
+       ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */
+       ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */
+       ECORE_EXE_USE_SH = 128, /**< Use /bin/sh to run the command. */
+       ECORE_EXE_NOT_LEADER = 256 /**< Do not use setsid() to have the executed process be its own session leader */
+     };
+   typedef enum _Ecore_Exe_Flags Ecore_Exe_Flags;
+
+   enum _Ecore_Exe_Win32_Priority
+     {
+       ECORE_EXE_WIN32_PRIORITY_IDLE, /**< Idle priority, for monitoring the system */
+       ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL, /**< Below default priority */
+       ECORE_EXE_WIN32_PRIORITY_NORMAL, /**< Default priority */
+       ECORE_EXE_WIN32_PRIORITY_ABOVE_NORMAL, /**< Above default priority */
+       ECORE_EXE_WIN32_PRIORITY_HIGH, /**< High priority, use with care as other threads in the system will not get processor time */
+       ECORE_EXE_WIN32_PRIORITY_REALTIME /**< Realtime priority, should be almost never used as it can interrupt system threads that manage mouse input, keyboard input, and background disk flushing */
+     };
+   typedef enum _Ecore_Exe_Win32_Priority Ecore_Exe_Win32_Priority;
+
+   enum _Ecore_Poller_Type /* Poller types */
+     {
+       ECORE_POLLER_CORE = 0 /**< The core poller interval */
+     };
+   typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
+
+   typedef struct _Ecore_Exe                   Ecore_Exe; /**< A handle for spawned processes */
+   typedef struct _Ecore_Timer                 Ecore_Timer; /**< A handle for timers */
+   typedef struct _Ecore_Idler                 Ecore_Idler; /**< A handle for idlers */
+   typedef struct _Ecore_Idle_Enterer          Ecore_Idle_Enterer; /**< A handle for idle enterers */
+   typedef struct _Ecore_Idle_Exiter           Ecore_Idle_Exiter; /**< A handle for idle exiters */
+   typedef struct _Ecore_Fd_Handler            Ecore_Fd_Handler; /**< A handle for Fd handlers */
+   typedef struct _Ecore_Win32_Handler         Ecore_Win32_Handler; /**< A handle for HANDLE handlers on Windows */
+   typedef struct _Ecore_Event_Handler         Ecore_Event_Handler; /**< A handle for an event handler */
+   typedef struct _Ecore_Event_Filter          Ecore_Event_Filter; /**< A handle for an event filter */
+   typedef struct _Ecore_Event                 Ecore_Event; /**< A handle for an event */
+   typedef struct _Ecore_Animator              Ecore_Animator; /**< A handle for animators */
+   typedef struct _Ecore_Pipe                  Ecore_Pipe; /**< A handle for pipes */
+   typedef struct _Ecore_Poller                Ecore_Poller; /**< A handle for pollers */
+   typedef struct _Ecore_Event_Signal_User     Ecore_Event_Signal_User; /**< User signal event */
+   typedef struct _Ecore_Event_Signal_Hup      Ecore_Event_Signal_Hup; /**< Hup signal event */
+   typedef struct _Ecore_Event_Signal_Exit     Ecore_Event_Signal_Exit; /**< Exit signal event */
+   typedef struct _Ecore_Event_Signal_Power    Ecore_Event_Signal_Power; /**< Power signal event */
+   typedef struct _Ecore_Event_Signal_Realtime Ecore_Event_Signal_Realtime; /**< Realtime signal event */
+   typedef struct _Ecore_Exe_Event_Add         Ecore_Exe_Event_Add; /**< Spawned Exe add event */
+   typedef struct _Ecore_Exe_Event_Del         Ecore_Exe_Event_Del; /**< Spawned Exe exit event */
+   typedef struct _Ecore_Exe_Event_Data_Line   Ecore_Exe_Event_Data_Line; /**< Lines from a child process */
+   typedef struct _Ecore_Exe_Event_Data        Ecore_Exe_Event_Data; /**< Data from a child process */
+   typedef struct _Ecore_Thread                Ecore_Thread;
+
+   typedef struct _Ecore_Job Ecore_Job; /**< A job handle */
+
+   struct _Ecore_Event_Signal_User /** User signal event */
+     {
+       int   number; /**< The signal number. Either 1 or 2 */
+       void *ext_data; /**< Extension data - not used */
+
+#ifndef _WIN32
+       siginfo_t data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Event_Signal_Hup /** Hup signal event */
+     {
+       void *ext_data; /**< Extension data - not used */
+
+#ifndef _WIN32
+       siginfo_t data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Event_Signal_Exit /** Exit request event */
+     {
+       unsigned int   interrupt : 1; /**< Set if the exit request was an interrupt  signal*/
+       unsigned int   quit      : 1; /**< set if the exit request was a quit signal */
+       unsigned int   terminate : 1; /**< Set if the exit request was a terminate singal */
+       void          *ext_data;        /**< Extension data - not used */
+
+#ifndef _WIN32
+       siginfo_t data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Event_Signal_Power /** Power event */
+     {
+       void *ext_data; /**< Extension data - not used */
+
+#ifndef _WIN32
+       siginfo_t data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Event_Signal_Realtime /** Realtime event */
+     {
+       int num; /**< The realtime signal's number */
+
+#ifndef _WIN32
+       siginfo_t data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Exe_Event_Add /** Process add event */
+     {
+       Ecore_Exe *exe; /**< The handle to the added process */
+       void      *ext_data; /**< Extension data - not used */
+     };
+
+   struct _Ecore_Exe_Event_Del /** Process exit event */
+     {
+       pid_t         pid; /**< The process ID of the process that exited */
+       int           exit_code; /**< The exit code of the process */
+       Ecore_Exe    *exe; /**< The handle to the exited process, or NULL if not found */
+       int           exit_signal; /** < The signal that caused the process to exit */
+       unsigned int  exited    : 1; /** < set to 1 if the process exited of its own accord */
+       unsigned int  signalled : 1; /** < set to 1 id the process exited due to uncaught signal */
+       void         *ext_data; /**< Extension data - not used */
+#ifndef _WIN32
+       siginfo_t     data; /**< Signal info */
+#endif
+     };
+
+   struct _Ecore_Exe_Event_Data_Line /**< Lines from a child process */
+      {
+         char *line;
+        int   size;
+      };
+
+   struct _Ecore_Exe_Event_Data /** Data from a child process event */
+     {
+       Ecore_Exe *exe; /**< The handle to the process */
+       void *data; /**< the raw binary data from the child process that was recieved */
+       int   size; /**< the size of this data in bytes */
+       Ecore_Exe_Event_Data_Line *lines; /**< an array of line data if line buffered, the last one has it's line member set to NULL */
+     };
+
+   EAPI int  ecore_init(void);
+   EAPI int  ecore_shutdown(void);
+
+   EAPI void ecore_app_args_set(int argc, const char **argv);
+   EAPI void ecore_app_args_get(int *argc, char ***argv);
+   EAPI void ecore_app_restart(void);
+
+   EAPI Ecore_Event_Handler *ecore_event_handler_add(int type, int (*func) (void *data, int type, void *event), const void *data);
+   EAPI void                *ecore_event_handler_del(Ecore_Event_Handler *event_handler);
+   EAPI Ecore_Event         *ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data);
+   EAPI void                *ecore_event_del(Ecore_Event *event);
+   EAPI int                  ecore_event_type_new(void);
+   EAPI Ecore_Event_Filter  *ecore_event_filter_add(void * (*func_start) (void *data), int (*func_filter) (void *data, void *loop_data, int type, void *event), void (*func_end) (void *data, void *loop_data), const void *data);
+   EAPI void                *ecore_event_filter_del(Ecore_Event_Filter *ef);
+   EAPI int                  ecore_event_current_type_get(void);
+   EAPI void                *ecore_event_current_event_get(void);
+
+
+   EAPI void        ecore_exe_run_priority_set(int pri);
+   EAPI int         ecore_exe_run_priority_get(void);
+   EAPI Ecore_Exe  *ecore_exe_run(const char *exe_cmd, const void *data);
+   EAPI Ecore_Exe  *ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data);
+   EAPI void        ecore_exe_callback_pre_free_set(Ecore_Exe *exe, void (*func)(void *data, const Ecore_Exe *exe));
+   EAPI Eina_Bool   ecore_exe_send(Ecore_Exe *exe, const void *data, int size);
+   EAPI void        ecore_exe_close_stdin(Ecore_Exe *exe);
+   EAPI void        ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines);
+   EAPI Ecore_Exe_Event_Data *ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags);
+   EAPI void        ecore_exe_event_data_free(Ecore_Exe_Event_Data *data);
+   EAPI void       *ecore_exe_free(Ecore_Exe *exe);
+   EAPI pid_t       ecore_exe_pid_get(const Ecore_Exe *exe);
+   EAPI void        ecore_exe_tag_set(Ecore_Exe *exe, const char *tag);
+   EAPI const char *ecore_exe_tag_get(const Ecore_Exe *exe);
+   EAPI const char *ecore_exe_cmd_get(const Ecore_Exe *exe);
+   EAPI void       *ecore_exe_data_get(const Ecore_Exe *exe);
+   EAPI Ecore_Exe_Flags ecore_exe_flags_get(const Ecore_Exe *exe);
+   EAPI void        ecore_exe_pause(Ecore_Exe *exe);
+   EAPI void        ecore_exe_continue(Ecore_Exe *exe);
+   EAPI void        ecore_exe_interrupt(Ecore_Exe *exe);
+   EAPI void        ecore_exe_quit(Ecore_Exe *exe);
+   EAPI void        ecore_exe_terminate(Ecore_Exe *exe);
+   EAPI void        ecore_exe_kill(Ecore_Exe *exe);
+   EAPI void        ecore_exe_signal(Ecore_Exe *exe, int num);
+   EAPI void        ecore_exe_hup(Ecore_Exe *exe);
+
+   EAPI Ecore_Idler *ecore_idler_add(int (*func) (void *data), const void *data);
+   EAPI void        *ecore_idler_del(Ecore_Idler *idler);
+
+   EAPI Ecore_Idle_Enterer *ecore_idle_enterer_add(int (*func) (void *data), const void *data);
+   EAPI Ecore_Idle_Enterer *ecore_idle_enterer_before_add(int (*func) (void *data), const void *data);
+   EAPI void               *ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer);
+
+   EAPI Ecore_Idle_Exiter *ecore_idle_exiter_add(int (*func) (void *data), const void *data);
+   EAPI void              *ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);
+
+   EAPI void              ecore_main_loop_iterate(void);
+
+   EAPI void              ecore_main_loop_select_func_set(int (*func)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout));
+   EAPI void             *ecore_main_loop_select_func_get(void);
+
+   EAPI Eina_Bool         ecore_main_loop_glib_integrate(void);
+   EAPI void              ecore_main_loop_glib_always_integrate_disable(void);
+       
+   EAPI void              ecore_main_loop_begin(void);
+   EAPI void              ecore_main_loop_quit(void);
+   EAPI Ecore_Fd_Handler *ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data);
+   EAPI void              ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data);
+   EAPI void             *ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler);
+   EAPI int               ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler);
+   EAPI int               ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags);
+   EAPI void              ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags);
+
+   EAPI Ecore_Win32_Handler *ecore_main_win32_handler_add(void *h, int (*func) (void *data, Ecore_Win32_Handler *wh), const void *data);
+   EAPI void                *ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler);
+
+   EAPI Ecore_Pipe  *ecore_pipe_add(void (*handler) (void *data, void *buffer, unsigned int nbyte), const void *data);
+   EAPI void        *ecore_pipe_del(Ecore_Pipe *p);
+   EAPI int          ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes);
+   EAPI void         ecore_pipe_write_close(Ecore_Pipe *p);
+   EAPI void         ecore_pipe_read_close(Ecore_Pipe *p);
+
+   EAPI Ecore_Thread *ecore_thread_run(void (*func_heavy)(void *data), void (*func_end)(void *data), void (*func_cancel)(void *data), const void *data);
+   EAPI Eina_Bool     ecore_thread_cancel(Ecore_Thread *thread);
+
+   EAPI double ecore_time_get(void);
+   EAPI double ecore_loop_time_get(void);
+
+   EAPI Ecore_Timer *ecore_timer_add(double in, int (*func) (void *data), const void *data);
+   EAPI Ecore_Timer *ecore_timer_loop_add(double in, int (*func) (void *data), const void *data);
+   EAPI void        *ecore_timer_del(Ecore_Timer *timer);
+   EAPI void         ecore_timer_interval_set(Ecore_Timer *timer, double in);
+   EAPI double       ecore_timer_interval_get(Ecore_Timer *timer);
+   EAPI void         ecore_timer_freeze(Ecore_Timer *timer);
+   EAPI void         ecore_timer_thaw(Ecore_Timer *timer);
+   EAPI void         ecore_timer_delay(Ecore_Timer *timer, double add);
+   EAPI double       ecore_timer_pending_get(Ecore_Timer *timer);
+
+   EAPI double       ecore_timer_precision_get(void);
+   EAPI void         ecore_timer_precision_set(double precision);
+
+   EAPI Ecore_Animator *ecore_animator_add(int (*func) (void *data), const void *data);
+   EAPI void           *ecore_animator_del(Ecore_Animator *animator);
+   EAPI void           ecore_animator_freeze(Ecore_Animator *animator);
+   EAPI void           ecore_animator_thaw(Ecore_Animator *animator);
+   EAPI void            ecore_animator_frametime_set(double frametime);
+   EAPI double          ecore_animator_frametime_get(void);
+
+   EAPI void          ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time);
+   EAPI double        ecore_poller_poll_interval_get(Ecore_Poller_Type type);
+   EAPI Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data);
+   EAPI void         *ecore_poller_del(Ecore_Poller *poller);
+
+   EAPI Ecore_Job *ecore_job_add(void (*func) (void *data), const void *data);
+   EAPI void      *ecore_job_del(Ecore_Job *job);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/lib/ecore/Ecore_Getopt.h b/src/lib/ecore/Ecore_Getopt.h
new file mode 100644 (file)
index 0000000..a36c7a0
--- /dev/null
@@ -0,0 +1,403 @@
+#ifndef _ECORE_GETOPT_H
+#define _ECORE_GETOPT_H
+
+#include <stdio.h>
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file Ecore_Getopt.h
+ * @brief Contains powerful getopt replacement.
+ *
+ * This replacement handles both short (-X) or long options (--ABC)
+ * options, with various actions supported, like storing one value and
+ * already converting to required type, counting number of
+ * occurrences, setting true or false values, show help, license,
+ * copyright and even support user-defined callbacks.
+ *
+ * It is provided a set of C Pre Processor macros so definition is
+ * straightforward.
+ *
+ * Values will be stored elsewhere indicated by an array of pointers
+ * to values, it is given in separate to parser description so you can
+ * use multiple values with the same parser.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  typedef enum {
+    ECORE_GETOPT_ACTION_STORE,
+    ECORE_GETOPT_ACTION_STORE_CONST,
+    ECORE_GETOPT_ACTION_STORE_TRUE,
+    ECORE_GETOPT_ACTION_STORE_FALSE,
+    ECORE_GETOPT_ACTION_CHOICE,
+    ECORE_GETOPT_ACTION_APPEND,
+    ECORE_GETOPT_ACTION_COUNT,
+    ECORE_GETOPT_ACTION_CALLBACK,
+    ECORE_GETOPT_ACTION_HELP,
+    ECORE_GETOPT_ACTION_VERSION,
+    ECORE_GETOPT_ACTION_COPYRIGHT,
+    ECORE_GETOPT_ACTION_LICENSE
+  } Ecore_Getopt_Action;
+
+  typedef enum {
+    ECORE_GETOPT_TYPE_STR,
+    ECORE_GETOPT_TYPE_BOOL,
+    ECORE_GETOPT_TYPE_SHORT,
+    ECORE_GETOPT_TYPE_INT,
+    ECORE_GETOPT_TYPE_LONG,
+    ECORE_GETOPT_TYPE_USHORT,
+    ECORE_GETOPT_TYPE_UINT,
+    ECORE_GETOPT_TYPE_ULONG,
+    ECORE_GETOPT_TYPE_DOUBLE
+  } Ecore_Getopt_Type;
+
+  typedef enum {
+    ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO = 0,
+    ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES = 1,
+    ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL = 3
+  } Ecore_Getopt_Desc_Arg_Requirement;
+
+  typedef union _Ecore_Getopt_Value             Ecore_Getopt_Value;
+
+  typedef struct _Ecore_Getopt_Desc_Store       Ecore_Getopt_Desc_Store;
+  typedef struct _Ecore_Getopt_Desc_Callback    Ecore_Getopt_Desc_Callback;
+  typedef struct _Ecore_Getopt_Desc             Ecore_Getopt_Desc;
+  typedef struct _Ecore_Getopt                  Ecore_Getopt;
+
+  union _Ecore_Getopt_Value
+  {
+     char **strp;
+     unsigned char *boolp;
+     short *shortp;
+     int *intp;
+     long *longp;
+     unsigned short *ushortp;
+     unsigned int *uintp;
+     unsigned long *ulongp;
+     double *doublep;
+     Eina_List **listp;
+     void **ptrp;
+  };
+
+  struct _Ecore_Getopt_Desc_Store
+  {
+     Ecore_Getopt_Type type;           /**< type of data being handled */
+     Ecore_Getopt_Desc_Arg_Requirement arg_req;
+     union
+     {
+       const char *strv;
+       unsigned char boolv;
+       short shortv;
+       int intv;
+       long longv;
+       unsigned short ushortv;
+       unsigned int uintv;
+       unsigned long ulongv;
+       double doublev;
+     } def;
+  };
+
+  struct _Ecore_Getopt_Desc_Callback
+  {
+     unsigned char (*func)(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, const char *str, void *data, Ecore_Getopt_Value *storage);
+     const void *data;
+     Ecore_Getopt_Desc_Arg_Requirement arg_req;
+     const char *def;
+  };
+
+  struct _Ecore_Getopt_Desc
+  {
+     char shortname;       /**< used with a single dash */
+     const char *longname; /**< used with double dashes */
+     const char *help;     /**< used by --help/ecore_getopt_help() */
+     const char *metavar;  /**< used by ecore_getopt_help() with nargs > 0 */
+
+     Ecore_Getopt_Action action; /**< define how to handle it */
+     union
+     {
+       const Ecore_Getopt_Desc_Store store;
+       const void *store_const;
+       const char *const *choices; /* NULL terminated. */
+       const Ecore_Getopt_Type append_type;
+       const Ecore_Getopt_Desc_Callback callback;
+       const void *dummy;
+     } action_param;
+  };
+
+  struct _Ecore_Getopt
+  {
+     const char *prog; /**< to be used when ecore_app_args_get() fails */
+     const char *usage; /**< usage example, %prog is replaced */
+     const char *version; /**< if exists, --version will work */
+     const char *copyright; /**< if exists, --copyright will work */
+     const char *license; /**< if exists, --license will work */
+     const char *description; /**< long description, possible multiline */
+     unsigned char strict : 1; /**< fail on errors */
+     const Ecore_Getopt_Desc descs[]; /* NULL terminated. */
+  };
+
+#define ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar, type, arg_requirement, default_value) \
+  {shortname, longname, help, metavar, ECORE_GETOPT_ACTION_STORE,      \
+       {.store = {type, arg_requirement, default_value}}}
+
+#define ECORE_GETOPT_STORE(shortname, longname, help, type)             \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, NULL, type,       \
+                         ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES, {})
+
+#define ECORE_GETOPT_STORE_STR(shortname, longname, help)               \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_STR)
+#define ECORE_GETOPT_STORE_BOOL(shortname, longname, help)              \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_BOOL)
+#define ECORE_GETOPT_STORE_SHORT(shortname, longname, help)             \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_SHORT)
+#define ECORE_GETOPT_STORE_INT(shortname, longname, help)               \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_INT)
+#define ECORE_GETOPT_STORE_LONG(shortname, longname, help)              \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_LONG)
+#define ECORE_GETOPT_STORE_USHORT(shortname, longname, help)            \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_USHORT)
+#define ECORE_GETOPT_STORE_UINT(shortname, longname, help)              \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_UINT)
+#define ECORE_GETOPT_STORE_ULONG(shortname, longname, help)             \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_ULONG)
+#define ECORE_GETOPT_STORE_DOUBLE(shortname, longname, help)            \
+  ECORE_GETOPT_STORE(shortname, longname, help, ECORE_GETOPT_TYPE_DOUBLE)
+
+
+#define ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, type) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar, type,    \
+                         ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES, {})
+
+#define ECORE_GETOPT_STORE_METAVAR_STR(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_STR)
+#define ECORE_GETOPT_STORE_METAVAR_BOOL(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_BOOL)
+#define ECORE_GETOPT_STORE_METAVAR_SHORT(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_SHORT)
+#define ECORE_GETOPT_STORE_METAVAR_INT(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_INT)
+#define ECORE_GETOPT_STORE_METAVAR_LONG(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_LONG)
+#define ECORE_GETOPT_STORE_METAVAR_USHORT(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_USHORT)
+#define ECORE_GETOPT_STORE_METAVAR_UINT(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_UINT)
+#define ECORE_GETOPT_STORE_METAVAR_ULONG(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_ULONG)
+#define ECORE_GETOPT_STORE_METAVAR_DOUBLE(shortname, longname, help, metavar) \
+  ECORE_GETOPT_STORE_METAVAR(shortname, longname, help, metavar, ECORE_GETOPT_TYPE_DOUBLE)
+
+
+#define ECORE_GETOPT_STORE_DEF(shortname, longname, help, type, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, NULL, type,       \
+                         ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL,   \
+                         default_value)
+
+#define ECORE_GETOPT_STORE_DEF_STR(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_STR,                         \
+                        {.strv = default_value})
+#define ECORE_GETOPT_STORE_DEF_BOOL(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_BOOL,                        \
+                        {.boolv = default_value})
+#define ECORE_GETOPT_STORE_DEF_SHORT(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_SHORT,                       \
+                        {.shortv = default_value})
+#define ECORE_GETOPT_STORE_DEF_INT(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_INT,                         \
+                        {.intv = default_value})
+#define ECORE_GETOPT_STORE_DEF_LONG(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_LONG,                        \
+                        {.longv = default_value})
+#define ECORE_GETOPT_STORE_DEF_USHORT(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_USHORT,                      \
+                        {.ushortv = default_value})
+#define ECORE_GETOPT_STORE_DEF_UINT(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_UINT,                        \
+                        {.uintv, default_value})
+#define ECORE_GETOPT_STORE_DEF_ULONG(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_ULONG,                       \
+                        {.ulongv = default_value})
+#define ECORE_GETOPT_STORE_DEF_DOUBLE(shortname, longname, help, default_value) \
+  ECORE_GETOPT_STORE_DEF(shortname, longname, help,                    \
+                        ECORE_GETOPT_TYPE_DOUBLE,                      \
+                        {.doublev = default_value})
+
+#define ECORE_GETOPT_STORE_FULL_STR(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_STR,                        \
+                         arg_requirement,                              \
+                         {.strv = default_value})
+#define ECORE_GETOPT_STORE_FULL_BOOL(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_BOOL,                       \
+                         arg_requirement,                              \
+                         {.boolv = default_value})
+#define ECORE_GETOPT_STORE_FULL_SHORT(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_SHORT,                      \
+                         arg_requirement,                              \
+                         {.shortv = default_value})
+#define ECORE_GETOPT_STORE_FULL_INT(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_INT,                        \
+                         arg_requirement,                              \
+                         {.intv = default_value})
+#define ECORE_GETOPT_STORE_FULL_LONG(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_LONG,                       \
+                         arg_requirement,                              \
+                         {.longv = default_value})
+#define ECORE_GETOPT_STORE_FULL_USHORT(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_USHORT,                     \
+                         arg_requirement,                              \
+                         {.ushortv = default_value})
+#define ECORE_GETOPT_STORE_FULL_UINT(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_UINT,                       \
+                         arg_requirement,                              \
+                         {.uintv, default_value})
+#define ECORE_GETOPT_STORE_FULL_ULONG(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_ULONG,                      \
+                         arg_requirement,                              \
+                         {.ulongv = default_value})
+#define ECORE_GETOPT_STORE_FULL_DOUBLE(shortname, longname, help, metavar, arg_requirement, default_value) \
+  ECORE_GETOPT_STORE_FULL(shortname, longname, help, metavar,          \
+                         ECORE_GETOPT_TYPE_DOUBLE,                     \
+                         arg_requirement,                              \
+                         {.doublev = default_value})
+
+#define ECORE_GETOPT_STORE_CONST(shortname, longname, help, value)      \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_STORE_CONST,   \
+       {.store_const = value}}
+#define ECORE_GETOPT_STORE_TRUE(shortname, longname, help)              \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_STORE_TRUE,    \
+       {.dummy = NULL}}
+#define ECORE_GETOPT_STORE_FALSE(shortname, longname, help)             \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_STORE_FALSE,   \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_CHOICE(shortname, longname, help, choices_array)   \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_CHOICE,                \
+       {.choices = choices_array}}
+#define ECORE_GETOPT_CHOICE_METAVAR(shortname, longname, help, metavar, choices_array) \
+  {shortname, longname, help, metavar, ECORE_GETOPT_ACTION_CHOICE,     \
+       {.choices = choices_array}}
+
+
+#define ECORE_GETOPT_APPEND(shortname, longname, help, sub_type)        \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_APPEND,                \
+       {.append_type = sub_type}}
+#define ECORE_GETOPT_APPEND_METAVAR(shortname, longname, help, metavar, type) \
+  {shortname, longname, help, metavar, ECORE_GETOPT_ACTION_APPEND,     \
+       {.append_type = type}}
+
+#define ECORE_GETOPT_COUNT(shortname, longname, help)                  \
+  {shortname, longname, help, NULL, ECORE_GETOPT_ACTION_COUNT,         \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_CALLBACK_FULL(shortname, longname, help, metavar, callback_func, callback_data, argument_requirement, default_value) \
+  {shortname, longname, help, metavar, ECORE_GETOPT_ACTION_CALLBACK,   \
+       {.callback = {callback_func, callback_data,                     \
+                    argument_requirement, default_value}}}
+#define ECORE_GETOPT_CALLBACK_NOARGS(shortname, longname, help, callback_func, callback_data) \
+  ECORE_GETOPT_CALLBACK_FULL(shortname, longname, help, NULL,          \
+                            callback_func, callback_data,              \
+                            ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO,      \
+                            NULL)
+#define ECORE_GETOPT_CALLBACK_ARGS(shortname, longname, help, metavar, callback_func, callback_data) \
+  ECORE_GETOPT_CALLBACK_FULL(shortname, longname, help, metavar,       \
+                            callback_func, callback_data,              \
+                            ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES,     \
+                            NULL)
+
+#define ECORE_GETOPT_HELP(shortname, longname)                         \
+  {shortname, longname, "show this message.", NULL,                    \
+       ECORE_GETOPT_ACTION_HELP,                                       \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_VERSION(shortname, longname)                      \
+  {shortname, longname, "show program version.", NULL,                 \
+       ECORE_GETOPT_ACTION_VERSION,                                    \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_COPYRIGHT(shortname, longname)                    \
+  {shortname, longname, "show copyright.", NULL,                       \
+       ECORE_GETOPT_ACTION_COPYRIGHT,                                  \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_LICENSE(shortname, longname)                      \
+  {shortname, longname, "show license.", NULL,                         \
+       ECORE_GETOPT_ACTION_LICENSE,                                    \
+       {.dummy = NULL}}
+
+#define ECORE_GETOPT_SENTINEL {0, NULL, NULL, NULL, 0, {.dummy = NULL}}
+
+#define ECORE_GETOPT_VALUE_STR(val)      {.strp = &(val)}
+#define ECORE_GETOPT_VALUE_BOOL(val)     {.boolp = &(val)}
+#define ECORE_GETOPT_VALUE_SHORT(val)    {.shortp = &(val)}
+#define ECORE_GETOPT_VALUE_INT(val)      {.intp = &(val)}
+#define ECORE_GETOPT_VALUE_LONG(val)     {.longp = &(val)}
+#define ECORE_GETOPT_VALUE_USHORT(val)   {.ushortp = &(val)}
+#define ECORE_GETOPT_VALUE_UINT(val)     {.uintp = &(val)}
+#define ECORE_GETOPT_VALUE_ULONG(val)    {.ulongp = &(val)}
+#define ECORE_GETOPT_VALUE_DOUBLE(val)   {.doublep = &(val)}
+#define ECORE_GETOPT_VALUE_PTR(val)      {.ptrp = &(val)}
+#define ECORE_GETOPT_VALUE_PTR_CAST(val) {.ptrp = (void **)&(val)}
+#define ECORE_GETOPT_VALUE_LIST(val)     {.listp = &(val)}
+#define ECORE_GETOPT_VALUE_NONE          {.ptrp = NULL}
+
+  EAPI void ecore_getopt_help(FILE *fp, const Ecore_Getopt *info);
+
+  EAPI unsigned char ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser);
+  EAPI int ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv);
+
+  EAPI Eina_List *ecore_getopt_list_free(Eina_List *list);
+
+  /* helper functions to be used with ECORE_GETOPT_CALLBACK_*() */
+  EAPI unsigned char ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, const char *str, void *data, Ecore_Getopt_Value *storage);
+  EAPI unsigned char ecore_getopt_callback_size_parse(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, const char *str, void *data, Ecore_Getopt_Value *storage);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ECORE_GETOPT_H */
diff --git a/src/lib/ecore/Makefile.am b/src/lib/ecore/Makefile.am
new file mode 100644 (file)
index 0000000..c1fb716
--- /dev/null
@@ -0,0 +1,50 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = @GLIB_CFLAGS@ @EVIL_CFLAGS@ @EINA_CFLAGS@ @WIN32_CPPFLAGS@ @EFL_ECORE_BUILD@
+AM_CFLAGS = @WIN32_CFLAGS@ @EFL_PTHREAD_CFLAGS@
+
+lib_LTLIBRARIES = libecore.la
+include_HEADERS = \
+Ecore.h \
+Ecore_Getopt.h
+
+libecore_la_SOURCES = \
+ecore.c \
+ecore_anim.c \
+ecore_app.c \
+ecore_events.c \
+ecore_getopt.c \
+ecore_idle_enterer.c \
+ecore_idle_exiter.c \
+ecore_idler.c \
+ecore_job.c \
+ecore_main.c \
+ecore_pipe.c \
+ecore_poll.c \
+ecore_time.c \
+ecore_timer.c \
+ecore_thread.c \
+ecore_glib.c
+
+if ECORE_HAVE_WIN32
+
+libecore_la_SOURCES += ecore_exe_win32.c
+
+else
+
+if ECORE_HAVE_WINCE
+
+libecore_la_SOURCES += ecore_exe_wince.c
+
+else
+
+libecore_la_SOURCES += ecore_signal.c ecore_exe.c
+
+endif
+
+endif
+
+libecore_la_LIBADD = @dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ -lm
+libecore_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_release_info@
+
+EXTRA_DIST = ecore_private.h
diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c
new file mode 100644 (file)
index 0000000..8ccb8d2
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+#include <Eina.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#if HAVE_MALLINFO
+#include <malloc.h>
+
+#define KEEP_MAX(Global, Local)                        \
+   if (Global < (Local))                       \
+     Global = Local;
+
+static int _ecore_memory_statistic(void *data);
+static int _ecore_memory_max_total = 0;
+static int _ecore_memory_max_free = 0;
+static pid_t _ecore_memory_pid = 0;
+#endif
+
+static const char *_ecore_magic_string_get(Ecore_Magic m);
+static int _ecore_init_count = 0;
+int _ecore_log_dom = -1;
+int _ecore_fps_debug = 0;
+
+/** OpenBSD does not define CODESET
+ * FIXME ??
+ */
+
+#ifndef CODESET
+# define CODESET "INVALID"
+#endif
+
+/**
+ * Set up connections, signal handlers, sockets etc.
+ * @return 1 or greater on success, 0 otherwise
+ *
+ * This function sets up all singal handlers and the basic event loop. If it
+ * succeeds, 1 will be returned, otherwise 0 will be returned.
+ *
+ * @code
+ * #include <Ecore.h>
+ *
+ * int main(int argc, char **argv)
+ * {
+ *   if (!ecore_init())
+ *   {
+ *     printf("ERROR: Cannot init Ecore!\n");
+ *     return -1;
+ *   }
+ *   ecore_main_loop_begin();
+ *   ecore_shutdown();
+ * }
+ * @endcode
+ */
+EAPI int
+ecore_init(void)
+{
+   if (++_ecore_init_count != 1)
+     return _ecore_init_count;
+
+#ifdef HAVE_LOCALE_H
+   setlocale(LC_CTYPE, "");
+#endif
+   /*
+     if (strcmp(nl_langinfo(CODESET), "UTF-8"))
+     {
+       WRN("Not a utf8 locale!");
+     }
+   */
+#ifdef HAVE_EVIL
+   if (!evil_init())
+     return --_ecore_init_count;
+#endif
+   if (!eina_init())
+     goto shutdown_evil;
+   _ecore_log_dom = eina_log_domain_register("Ecore",ECORE_DEFAULT_LOG_COLOR);
+   if (_ecore_log_dom < 0) {
+     EINA_LOG_ERR("Ecore was unable to create a log domain.");
+     goto shutdown_log_dom;
+   }
+   if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
+   if (_ecore_fps_debug) _ecore_fps_debug_init();
+   _ecore_signal_init();
+   _ecore_exe_init();
+   _ecore_thread_init();
+   _ecore_glib_init();
+   _ecore_job_init();
+   _ecore_loop_time = ecore_time_get();
+
+#if HAVE_MALLINFO
+   if (getenv("ECORE_MEM_STAT"))
+     {
+       _ecore_memory_pid = getpid();
+       ecore_animator_add(_ecore_memory_statistic, NULL);
+     }
+#endif
+
+#ifdef GLIB_INTEGRATION_ALWAYS   
+   if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
+#endif
+   
+   return _ecore_init_count;
+
+ shutdown_log_dom:
+   eina_shutdown();
+ shutdown_evil:
+#ifdef HAVE_EVIL
+   evil_shutdown();
+#endif
+   return --_ecore_init_count;
+}
+
+/**
+ * Shut down connections, signal handlers sockets etc.
+ *
+ * This function shuts down all things set up in ecore_init() and cleans up all
+ * event queues, handlers, filters, timers, idlers, idle enterers/exiters
+ * etc. set up after ecore_init() was called.
+ *
+ * Do not call this function from any callback that may be called from the main
+ * loop, as the main loop will then fall over and not function properly.
+ */
+EAPI int
+ecore_shutdown(void)
+{
+   if (--_ecore_init_count != 0)
+     return _ecore_init_count;
+
+   if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
+   _ecore_poller_shutdown();
+   _ecore_animator_shutdown();
+   _ecore_glib_shutdown();
+   _ecore_job_shutdown();
+   _ecore_thread_shutdown();
+   _ecore_exe_shutdown();
+   _ecore_idle_enterer_shutdown();
+   _ecore_idle_exiter_shutdown();
+   _ecore_idler_shutdown();
+   _ecore_timer_shutdown();
+   _ecore_event_shutdown();
+   _ecore_main_shutdown();
+   _ecore_signal_shutdown();
+
+#if HAVE_MALLINFO
+   if (getenv("ECORE_MEM_STAT"))
+     {
+       _ecore_memory_statistic(NULL);
+
+       ERR("[%i] Memory MAX total: %i, free: %i",
+           _ecore_memory_pid,
+           _ecore_memory_max_total,
+           _ecore_memory_max_free);
+     }
+#endif
+
+   eina_log_domain_unregister(_ecore_log_dom);
+   _ecore_log_dom = -1;
+   eina_shutdown();
+#ifdef HAVE_EVIL
+   evil_shutdown();
+#endif
+
+   return _ecore_init_count;
+}
+
+EAPI void
+ecore_print_warning(const char *function, const char *sparam)
+{
+   WRN("***** Developer Warning ***** :\n"
+       "\tThis program is calling:\n\n"
+       "\t%s();\n\n"
+       "\tWith the parameter:\n\n"
+       "\t%s\n\n"
+       "\tbeing NULL. Please fix your program.", function, sparam);
+   if (getenv("ECORE_ERROR_ABORT")) abort();
+}
+
+EAPI void
+_ecore_magic_fail(const void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname)
+{
+   ERR("\n"
+       "*** ECORE ERROR: Ecore Magic Check Failed!!!\n"
+       "*** IN FUNCTION: %s()", fname);
+   if (!d)
+     ERR("  Input handle pointer is NULL!");
+   else if (m == ECORE_MAGIC_NONE)
+     ERR("  Input handle has already been freed!");
+   else if (m != req_m)
+     ERR("  Input handle is wrong type\n"
+        "    Expected: %08x - %s\n"
+        "    Supplied: %08x - %s",
+        (unsigned int)req_m, _ecore_magic_string_get(req_m),
+        (unsigned int)m, _ecore_magic_string_get(m));
+     ERR("*** NAUGHTY PROGRAMMER!!!\n"
+        "*** SPANK SPANK SPANK!!!\n"
+        "*** Now go fix your code. Tut tut tut!");
+   if (getenv("ECORE_ERROR_ABORT")) abort();
+}
+
+static const char *
+_ecore_magic_string_get(Ecore_Magic m)
+{
+   switch (m)
+     {
+      case ECORE_MAGIC_NONE:
+       return "None (Freed Object)";
+       break;
+      case ECORE_MAGIC_EXE:
+       return "Ecore_Exe (Executable)";
+       break;
+      case ECORE_MAGIC_TIMER:
+       return "Ecore_Timer (Timer)";
+       break;
+      case ECORE_MAGIC_IDLER:
+       return "Ecore_Idler (Idler)";
+       break;
+      case ECORE_MAGIC_IDLE_ENTERER:
+       return "Ecore_Idle_Enterer (Idler Enterer)";
+       break;
+      case ECORE_MAGIC_IDLE_EXITER:
+       return "Ecore_Idle_Exiter (Idler Exiter)";
+       break;
+      case ECORE_MAGIC_FD_HANDLER:
+       return "Ecore_Fd_Handler (Fd Handler)";
+       break;
+      case ECORE_MAGIC_WIN32_HANDLER:
+       return "Ecore_Win32_Handler (Win32 Handler)";
+       break;
+      case ECORE_MAGIC_EVENT_HANDLER:
+       return "Ecore_Event_Handler (Event Handler)";
+       break;
+      case ECORE_MAGIC_EVENT:
+       return "Ecore_Event (Event)";
+       break;
+      default:
+       return "<UNKNOWN>";
+     };
+}
+
+/* fps debug calls - for debugging how much time your app actually spends */
+/* "running" (and the inverse being time spent running)... this does not */
+/* account for other apps and multitasking... */
+
+static int _ecore_fps_debug_init_count = 0;
+static int _ecore_fps_debug_fd = -1;
+unsigned int *_ecore_fps_runtime_mmap = NULL;
+
+void
+_ecore_fps_debug_init(void)
+{
+   char  buf[4096];
+   const char *tmp;
+   int   pid;
+
+   _ecore_fps_debug_init_count++;
+   if (_ecore_fps_debug_init_count > 1) return;
+
+#ifndef HAVE_EVIL
+   tmp = "/tmp";
+#else
+   tmp = (char *)evil_tmpdir_get ();
+#endif /* HAVE_EVIL */
+   pid = (int)getpid();
+   snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
+   _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
+   if (_ecore_fps_debug_fd < 0)
+     {
+       unlink(buf);
+       _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
+     }
+   if (_ecore_fps_debug_fd >= 0)
+     {
+       unsigned int zero = 0;
+       char *buf = (char *)&zero;
+       ssize_t todo = sizeof(unsigned int);
+
+       while (todo > 0)
+         {
+            ssize_t r = write(_ecore_fps_debug_fd, buf, todo);
+            if (r > 0)
+              {
+                 todo -= r;
+                 buf += r;
+              }
+            else if ((r < 0) && (errno == EINTR))
+              continue;
+            else
+              {
+                 ERR("could not write to file '%s' fd %d: %s",
+                     tmp, _ecore_fps_debug_fd, strerror(errno));
+                 close(_ecore_fps_debug_fd);
+                 _ecore_fps_debug_fd = -1;
+                 return;
+              }
+         }
+       _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int),
+                                      PROT_READ | PROT_WRITE,
+                                      MAP_SHARED,
+                                      _ecore_fps_debug_fd, 0);
+       if (_ecore_fps_runtime_mmap == MAP_FAILED)
+         _ecore_fps_runtime_mmap = NULL;
+     }
+}
+
+void
+_ecore_fps_debug_shutdown(void)
+{
+   _ecore_fps_debug_init_count--;
+   if (_ecore_fps_debug_init_count > 0) return;
+   if (_ecore_fps_debug_fd >= 0)
+     {
+        char buf[4096];
+        const char *tmp;
+        int   pid;
+
+#ifndef HAVE_EVIL
+   tmp = "/tmp";
+#else
+   tmp = (char *)evil_tmpdir_get ();
+#endif /* HAVE_EVIL */
+   pid = (int)getpid();
+       snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
+       unlink(buf);
+       if (_ecore_fps_runtime_mmap)
+         {
+            munmap(_ecore_fps_runtime_mmap, sizeof(int));
+            _ecore_fps_runtime_mmap = NULL;
+         }
+       close(_ecore_fps_debug_fd);
+       _ecore_fps_debug_fd = -1;
+     }
+}
+
+void
+_ecore_fps_debug_runtime_add(double t)
+{
+   if ((_ecore_fps_debug_fd >= 0) &&
+       (_ecore_fps_runtime_mmap))
+     {
+       unsigned int tm;
+
+       tm = (unsigned int)(t * 1000000.0);
+       /* i know its not 100% theoretically guaranteed, but i'd say a write */
+       /* of an int could be considered atomic for all practical purposes */
+       /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */
+       /* this can run for about 4294 seconds becore looping. if you are */
+       /* doing performance testing in one run for over an hour... well */
+       /* time to restart or handle a loop condition :) */
+       *(_ecore_fps_runtime_mmap) += tm;
+     }
+}
+
+#if HAVE_MALLINFO
+static int
+_ecore_memory_statistic(__UNUSED__ void *data)
+{
+   struct mallinfo mi;
+   static int uordblks = 0;
+   static int fordblks = 0;
+   Eina_Bool changed = EINA_FALSE;
+
+   mi = mallinfo();
+
+#define HAS_CHANGED(Global, Local)             \
+   if (Global != Local)                                \
+     {                                         \
+       Global = Local;                         \
+       changed = EINA_TRUE;                    \
+     }
+
+   HAS_CHANGED(uordblks, mi.uordblks);
+   HAS_CHANGED(fordblks, mi.fordblks);
+
+   if (changed)
+     ERR("[%i] Memory total: %i, free: %i",
+        _ecore_memory_pid,
+        mi.uordblks,
+        mi.fordblks);
+
+   KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
+   KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
+
+   return 1;
+}
+#endif
diff --git a/src/lib/ecore/ecore_anim.c b/src/lib/ecore/ecore_anim.c
new file mode 100644 (file)
index 0000000..96aa844
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Animator
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+
+   int           (*func) (void *data);
+   void          *data;
+
+   Eina_Bool     delete_me : 1;
+   Eina_Bool    suspended : 1;
+};
+
+
+static int _ecore_animator(void *data);
+
+static Ecore_Timer    *timer = NULL;
+static int             animators_delete_me = 0;
+static Ecore_Animator *animators = NULL;
+static double          animators_frametime = 1.0 / 30.0;
+
+/**
+ * Add a animator to tick off at every animaton tick during main loop execution.
+ * @param func The function to call when it ticks off
+ * @param data The data to pass to the function
+ * @return A handle to the new animator
+ * @ingroup Ecore_Animator_Group
+ *
+ * This function adds a animator and returns its handle on success and NULL on
+ * failure. The function @p func will be called every N seconds where N is the
+ * frametime interval set by ecore_animator_frametime_set(). The function will
+ * be passed the @p data pointer as its parameter.
+ *
+ * When the animator @p func is called, it must return a value of either 1 or 0.
+ * If it returns 1 (or ECORE_CALLBACK_RENEW), it will be called again at the
+ * next tick, or if it returns 0 (or ECORE_CALLBACK_CANCEL) it will be deleted
+ * automatically making any references/handles for it invalid.
+ */
+EAPI Ecore_Animator *
+ecore_animator_add(int (*func) (void *data), const void *data)
+{
+   Ecore_Animator *animator;
+
+   if (!func) return NULL;
+   animator = calloc(1, sizeof(Ecore_Animator));
+   if (!animator) return NULL;
+   ECORE_MAGIC_SET(animator, ECORE_MAGIC_ANIMATOR);
+   animator->func = func;
+   animator->data = (void *)data;
+   animators = (Ecore_Animator *)eina_inlist_append(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
+   if (!timer)
+     {
+        double t_loop = ecore_loop_time_get();
+        double sync_0 = 0.0;
+        double d = -fmod(t_loop - sync_0, animators_frametime);
+
+        timer = ecore_timer_loop_add(animators_frametime, _ecore_animator, NULL);
+        ecore_timer_delay(timer, d);
+     }
+   return animator;
+}
+
+/**
+ * Delete the specified animator from the animator list.
+ * @param animator The animator to delete
+ * @return The data pointer set for the animator
+ * @ingroup Ecore_Animator_Group
+ *
+ * Delete the specified @p aqnimator from the set of animators that are executed
+ * during main loop execution. This function returns the data parameter that
+ * was being passed to the callback on success, or NULL on failure. After this
+ * call returns the specified animator object @p animator is invalid and should not
+ * be used again. It will not get called again after deletion.
+ */
+EAPI void *
+ecore_animator_del(Ecore_Animator *animator)
+{
+   if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
+     {
+       ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
+                        "ecore_animator_del");
+       return NULL;
+     }
+   if (animator->delete_me) return animator->data;
+   animator->delete_me = EINA_TRUE;
+   animators_delete_me++;
+   return animator->data;
+}
+
+/**
+ * Set the animator call interval in seconds.
+ * @param frametime The time in seconds in between animator ticks.
+ *
+ * This function sets the time interval (in seconds) inbetween animator ticks.
+ */
+EAPI void
+ecore_animator_frametime_set(double frametime)
+{
+   if (frametime < 0.0) frametime = 0.0;
+   if (animators_frametime == frametime) return;
+   animators_frametime = frametime;
+   if (timer)
+     {
+       ecore_timer_del(timer);
+       timer = NULL;
+     }
+   if (animators)
+     timer = ecore_timer_add(animators_frametime, _ecore_animator, NULL);
+}
+
+/**
+ * Get the animator call interval in seconds.
+ * @return The time in second in between animator ticks.
+ *
+ * this function retrieves the time inbetween animator ticks, in seconds.
+ */
+EAPI double
+ecore_animator_frametime_get(void)
+{
+   return animators_frametime;
+}
+
+/**
+ * Suspend the specified animator.
+ * @param animator The animator to delete
+ * @ingroup Ecore_Animator_Group
+ *
+ * The specified @p animator will be temporarly removed from the set of animators
+ * that are executed during main loop execution.
+ */
+EAPI void
+ecore_animator_freeze(Ecore_Animator *animator)
+{
+   if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
+     {
+       ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
+                        "ecore_animator_del");
+       return;
+     }
+   if (animator->delete_me) return;
+   animator->suspended = EINA_TRUE;
+}
+
+/**
+ * Restore execution of the specified animator.
+ * @param animator The animator to delete
+ * @ingroup Ecore_Animator_Group
+ *
+ * The specified @p animator will be put back in the set of animators
+ * that are executed during main loop execution.
+ */
+EAPI void
+ecore_animator_thaw(Ecore_Animator *animator)
+{
+   if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
+     {
+       ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
+                        "ecore_animator_del");
+       return;
+     }
+   if (animator->delete_me) return;
+   animator->suspended = EINA_FALSE;
+}
+
+void
+_ecore_animator_shutdown(void)
+{
+   if (timer)
+     {
+       ecore_timer_del(timer);
+       timer = NULL;
+     }
+   while (animators)
+     {
+       Ecore_Animator *animator;
+
+       animator = animators;
+       animators = (Ecore_Animator *) eina_inlist_remove(EINA_INLIST_GET(animators), EINA_INLIST_GET(animators));
+       ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
+       free(animator);
+     }
+}
+
+static int
+_ecore_animator(void *data __UNUSED__)
+{
+   Ecore_Animator *animator;
+
+   EINA_INLIST_FOREACH(animators, animator)
+     {
+       if (!animator->delete_me && !animator->suspended)
+         {
+            if (!animator->func(animator->data))
+              {
+                 animator->delete_me = EINA_TRUE;
+                 animators_delete_me++;
+              }
+         }
+     }
+   if (animators_delete_me)
+     {
+       Ecore_Animator *l;
+       for(l = animators; l;)
+         {
+            animator = l;
+            l = (Ecore_Animator *) EINA_INLIST_GET(l)->next;
+            if (animator->delete_me)
+              {
+                 animators = (Ecore_Animator *) eina_inlist_remove(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
+                 ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
+                 free(animator);
+                 animators_delete_me--;
+                 if (animators_delete_me == 0) break;
+              }
+         }
+     }
+   if (!animators)
+     {
+       timer = NULL;
+       return 0;
+     }
+   return 1;
+}
diff --git a/src/lib/ecore/ecore_app.c b/src/lib/ecore/ecore_app.c
new file mode 100644 (file)
index 0000000..4e2b63e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#else
+# include <process.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+static int app_argc = 0;
+static char **app_argv = NULL;
+
+/**
+ * Set up the programs command-line arguments.
+ * @param argc The same as passed as argc to the programs main() function
+ * @param argv The same as passed as argv to the programs main() function
+ *
+ * A call to this function will store the programs command-line arguments
+ * for later use by ecore_app_restart() or ecore_app_args_get().
+ */
+EAPI void
+ecore_app_args_set(int argc, const char **argv)
+{
+   if ((argc < 1) ||
+       (!argv)) return;
+   app_argc = argc;
+   app_argv = (char **)argv;
+}
+
+/**
+ * Return the programs stored command-line arguments.
+ * @param argc A pointer to the return value to hold argc
+ * @param argv A pointer to the return value to hold argv
+ *
+ * When called, this funciton returns the arguments for the program stored by
+ * ecore_app_args_set(). The integer pointed to by @p argc will be filled, if
+ * the pointer is not NULL, and the string array pointer @p argv will be filled
+ * also if the pointer is not NULL. The values they are filled with will be the
+ * same set by ecore_app_args_set().
+ */
+EAPI void
+ecore_app_args_get(int *argc, char ***argv)
+{
+   if (argc) *argc = app_argc;
+   if (argv) *argv = app_argv;
+}
+
+/**
+ * Restart the program executable with the command-line arguments stored.
+ *
+ * This function will restart & re-execute this program in place of itself
+ * using the command-line arguments stored by ecore_app_args_set(). This is
+ * an easy way for a program to restart itself for cleanup purposes,
+ * configuration reasons or in the event of a crash.
+ */
+EAPI void
+ecore_app_restart(void)
+{
+   char *args[4096];
+   int i;
+
+   if ((app_argc < 1) || (!app_argv)) return;
+   if (app_argc >= 4096) return;
+   for (i = 0; i < app_argc; i++) args[i] = app_argv[i];
+   args[i] = NULL;
+   execvp(app_argv[0], args);
+}
diff --git a/src/lib/ecore/ecore_events.c b/src/lib/ecore/ecore_events.c
new file mode 100644 (file)
index 0000000..e30234d
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Event_Handler
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int type;
+   int (*func) (void *data, int type, void *event);
+   void  *data;
+   int       references;
+   Eina_Bool delete_me : 1;
+};
+
+struct _Ecore_Event_Filter
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   void *(*func_start) (void *data);
+   int (*func_filter) (void *data, void *loop_data, int type, void *event);
+   void (*func_end) (void *data, void *loop_data);
+   void *loop_data;
+   void *data;
+   int       references;
+   Eina_Bool delete_me : 1;
+};
+
+struct _Ecore_Event
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int type;
+   void *event;
+   void (*func_free) (void *data, void *ev);
+   void *data;
+   int       references;
+   Eina_Bool delete_me : 1;
+};
+
+
+static int events_num = 0;
+static Ecore_Event *events = NULL;
+static Ecore_Event *event_current = NULL;
+
+static Ecore_Event_Handler **event_handlers = NULL;
+static Ecore_Event_Handler *event_handler_current = NULL;
+static int event_handlers_num = 0;
+static int event_handlers_alloc_num = 0;
+static Eina_List *event_handlers_delete_list = NULL;
+
+static Ecore_Event_Filter *event_filters = NULL;
+static Ecore_Event_Filter *event_filter_current = NULL;
+static int event_filters_delete_me = 0;
+static int event_id_max = ECORE_EVENT_COUNT;
+static int ecore_raw_event_type = ECORE_EVENT_NONE;
+static void *ecore_raw_event_event =  NULL;
+
+
+static void _ecore_event_purge_deleted(void);
+static void *_ecore_event_del(Ecore_Event *event);
+
+
+/**
+ * Add an event handler.
+ * @param type The type of the event this handler will get called for
+ * @param func The function to call when the event is found in the queue
+ * @param data A data pointer to pass to the called function @p func
+ * @return A new Event handler, or NULL on failure
+ *
+ * Add an event handler to the list of handlers. This will, on success, return
+ * a handle to the event handler object that was created, that can be used
+ * later to remove the handler using ecore_event_handler_del(). The @p type
+ * parameter is the integer of the event type that will trigger this callback
+ * to be called. The callback @p func is called when this event is processed
+ * and will be passed the event type, a pointer to the private event
+ * structure that is specific to that event type, and a data pointer that is
+ * provided in this call as the @p data parameter.
+ *
+ * When the callback @p func is called, it must return 1 or 0. If it returns
+ * 1 (or ECORE_CALLBACK_RENEW), It will keep being called as per normal, for
+ * each handler set up for that event type. If it returns 0 (or
+ * ECORE_CALLBACK_CANCEL), it will cease processing handlers for that particular
+ * event, so all handler set to handle that event type that have not already
+ * been called, will not be.
+ */
+EAPI Ecore_Event_Handler *
+ecore_event_handler_add(int type, int (*func) (void *data, int type, void *event), const void *data)
+{
+   Ecore_Event_Handler *eh;
+
+   if (!func) return NULL;
+   if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) return NULL;
+   eh = calloc(1, sizeof(Ecore_Event_Handler));
+   if (!eh) return NULL;
+   ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER);
+   eh->type = type;
+   eh->func = func;
+   eh->data = (void *)data;
+   if (type >= (event_handlers_num - 1))
+     {
+       int p_alloc_num;
+
+       p_alloc_num = event_handlers_alloc_num;
+       event_handlers_num = type + 1;
+       if (event_handlers_num > event_handlers_alloc_num)
+         {
+            Ecore_Event_Handler **new_handlers;
+            int i;
+
+            event_handlers_alloc_num = ((event_handlers_num + 16) / 16) * 16;
+            new_handlers = realloc(event_handlers, event_handlers_alloc_num * sizeof(Ecore_Event_Handler *));
+            if (!new_handlers)
+              {
+                 free(eh);
+                 return NULL;
+              }
+            event_handlers = new_handlers;
+            for (i = p_alloc_num; i < event_handlers_alloc_num; i++)
+              event_handlers[i] = NULL;
+         }
+     }
+   event_handlers[type] = (Ecore_Event_Handler *) eina_inlist_append(EINA_INLIST_GET(event_handlers[type]), EINA_INLIST_GET(eh));
+   return eh;
+}
+
+/**
+ * Delete an event handler.
+ * @param event_handler Event handler handle to delete
+ * @return Data passed to handler
+ *
+ * Delete a specified event handler from the handler list. On success this will
+ * delete the event handler and return the pointer passed as @p data when the
+ * handler was added by ecore_event_handler_add(). On failure NULL will be
+ * returned. Once a handler is deleted it will no longer be called.
+ */
+EAPI void *
+ecore_event_handler_del(Ecore_Event_Handler *event_handler)
+{
+   if (!ECORE_MAGIC_CHECK(event_handler, ECORE_MAGIC_EVENT_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(event_handler, ECORE_MAGIC_EVENT_HANDLER,
+                        "ecore_event_handler_del");
+       return NULL;
+     }
+   event_handler->delete_me = 1;
+   event_handlers_delete_list = eina_list_append(event_handlers_delete_list, event_handler);
+   return event_handler->data;
+}
+
+static void
+_ecore_event_generic_free (void *data __UNUSED__, void *event)
+{
+   free (event);
+}
+
+/**
+ * Add an event to the event queue.
+ * @param type The event type to add to the end of the event queue
+ * @param ev The private data structure for this event type
+ * @param func_free The function to be called to free this private structure
+ * @param data The data pointer to be passed to the free function
+ * @return A Handle for that event
+ *
+ * On success this function returns a handle to an event on the event queue, or
+ * NULL if it fails. If it succeeds, an event of type @p type will be added
+ * to the queue for processing by event handlers added by
+ * ecore_event_handler_add(). The @p ev parameter will be a pointer to the event
+ * private data that is specific to that event type. When the event is no
+ * longer needed, @p func_free will be called and passed the private structure
+ * pointer for cleaning up. If @p func_free is NULL, free() will be called
+ * with the private structure pointer.
+ * func_free is passed @p data as its data parameter.
+ */
+EAPI Ecore_Event *
+ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data)
+{
+/*   if (!ev) return NULL;*/
+   if (type <= ECORE_EVENT_NONE) return NULL;
+   if (type >= event_id_max) return NULL;
+   if ((ev) && (!func_free)) func_free = _ecore_event_generic_free;
+   return _ecore_event_add(type, ev, func_free, data);
+}
+
+/**
+ * Delete an event from the queue.
+ * @param event The event handle to delete
+ * @return The data pointer originally set for the event free function
+ *
+ * This deletes the event @p event from the event queue, and returns the
+ * @p data parameer originally set when adding it with ecore_event_add(). This
+ * does not immediately call the free function, and it may be called later on
+ * cleanup, and so if the free function depends on the data pointer to work,
+ * you should defer cleaning of this till the free function is called later.
+ */
+EAPI void *
+ecore_event_del(Ecore_Event *event)
+{
+   if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT))
+     {
+       ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, "ecore_event_del");
+       return NULL;
+     }
+   event->delete_me = 1;
+   return event->data;
+}
+
+/**
+ * Allocate a new event type id sensibly and return the new id.
+ * @return A new event type id.
+ *
+ * This function allocates a new event type id and returns it. Once an event
+ * type has been allocated it can never be de-allocated during the life of
+ * the program. There is no guarantee of the contents of this event ID, or how
+ * it is calculated, except that the ID will be unique to the current instance
+ * of the process.
+ */
+EAPI int
+ecore_event_type_new(void)
+{
+   event_id_max++;
+   return event_id_max - 1;
+}
+
+/**
+ * Add a filter the current event queue.
+ * @param func_start Function to call just before filtering and return data
+ * @param func_filter Function to call on each event
+ * @param func_end Function to call after the queu has been filtered
+ * @param data Data to pass to the filter functions
+ * @return A filter handle
+ *
+ * This adds a filter to call callbacks to loop through the event queue and
+ * filter events out of the queue. On failure NULL is returned. On success a
+ * Filter handle is returned. Filters are called on the queue just before
+ * Event handler processing to try and remove redundant events. Just as
+ * processing starts @p func_start is called and passed the @p data pointer.
+ * This function returns a pointer that is used as loop_data that is now passed to
+ * @p func_filter as loop_data. @p func_filter is also passed @p data and the
+ * event type and private event structure. If this callback returns 0, the
+ * event is removed from the queue. If it returns 1, the event is kept. When
+ * processing is finished @p func_end is called and is passed the loop_data
+ * and @p data pointer to clean up.
+ */
+EAPI Ecore_Event_Filter *
+ecore_event_filter_add(void * (*func_start) (void *data), int (*func_filter) (void *data, void *loop_data, int type, void *event), void (*func_end) (void *data, void *loop_data), const void *data)
+{
+   Ecore_Event_Filter *ef;
+
+   if (!func_filter) return NULL;
+   ef = calloc(1, sizeof(Ecore_Event_Filter));
+   if (!ef) return NULL;
+   ECORE_MAGIC_SET(ef, ECORE_MAGIC_EVENT_FILTER);
+   ef->func_start = func_start;
+   ef->func_filter = func_filter;
+   ef->func_end = func_end;
+   ef->data = (void *)data;
+   event_filters = (Ecore_Event_Filter *) eina_inlist_append(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
+   return ef;
+}
+
+/**
+ * Delete an event filter.
+ * @param ef The event filter handle
+ * @return The data set for the filter
+ *
+ * Delete a filter that has been added by its @p ef handle. On success this
+ * will return the data pointer set when this filter was added. On failure
+ * NULL is returned.
+ */
+EAPI void *
+ecore_event_filter_del(Ecore_Event_Filter *ef)
+{
+   if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER))
+     {
+       ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, "ecore_event_filter_del");
+       return NULL;
+     }
+   ef->delete_me = 1;
+   event_filters_delete_me = 1;
+   return ef->data;
+}
+
+/**
+ * Return the current event type being handled.
+ * @return The current event type being handled if inside a handler callback
+ *
+ * If the program is currently inside an Ecore event handler callback this
+ * will return the type of the current event being processed. If Ecore is
+ * not inside an event handler, ECORE_EVENT_NONE is returned.
+ *
+ * This is useful when certain Ecore modules such as Ecore_Evas "swallow"
+ * events and not all the original information is passed on. In special cases
+ * this extra information may be useful or needed and using this call can let
+ * the program know if the event type being handled is one it wants to get more
+ * information about.
+ */
+EAPI int
+ecore_event_current_type_get(void)
+{
+   return ecore_raw_event_type;
+}
+
+/**
+ * Return the current event type pointer handled.
+ * @return The current event pointer being handled if inside a handler callback
+ *
+ * If the program is currently inside an Ecore event handler callback this
+ * will return the pointer of the current event being processed. If Ecore is
+ * not inside an event handler, NULL will be returned.
+ *
+ * This is useful when certain Ecore modules such as Ecore_Evas "swallow"
+ * events and not all the original information is passed on. In special cases
+ * this extra information may be useful or needed and using this call can let
+ * the program access the event data if the type of the event is handled by
+ * the program.
+ */
+EAPI void *
+ecore_event_current_event_get(void)
+{
+   return ecore_raw_event_event;
+}
+
+void
+_ecore_event_shutdown(void)
+{
+   int i;
+   Ecore_Event_Handler *eh;
+   Ecore_Event_Filter *ef;
+
+   while (events) _ecore_event_del(events);
+   event_current = NULL;
+   for (i = 0; i < event_handlers_num; i++)
+     {
+       while ((eh = event_handlers[i]))
+         {
+            event_handlers[i] = (Ecore_Event_Handler *) eina_inlist_remove(EINA_INLIST_GET(event_handlers[i]), EINA_INLIST_GET(event_handlers[i]));
+            ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
+            if (!eh->delete_me) free(eh);
+         }
+     }
+   EINA_LIST_FREE(event_handlers_delete_list, eh)
+     free(eh);
+   if (event_handlers) free(event_handlers);
+   event_handlers = NULL;
+   event_handlers_num = 0;
+   event_handlers_alloc_num = 0;
+   while ((ef = event_filters))
+     {
+       event_filters = (Ecore_Event_Filter *) eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(event_filters));
+       ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
+       free(ef);
+     }
+   event_filters_delete_me = 0;
+   event_filter_current = NULL;
+}
+
+int
+_ecore_event_exist(void)
+{
+   if (events) return 1;
+   return 0;
+}
+
+Ecore_Event *
+_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data)
+{
+   Ecore_Event *e;
+
+   e = calloc(1, sizeof(Ecore_Event));
+   if (!e) return NULL;
+   ECORE_MAGIC_SET(e, ECORE_MAGIC_EVENT);
+   e->type = type;
+   e->event = ev;
+   e->func_free = func_free;
+   e->data = data;
+   events = (Ecore_Event *) eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e));
+   events_num++;
+   return e;
+}
+
+void *
+_ecore_event_del(Ecore_Event *event)
+{
+   void *data;
+
+   data = event->data;
+   if (event->func_free) event->func_free(event->data, event->event);
+   events = (Ecore_Event *) eina_inlist_remove(EINA_INLIST_GET(events), EINA_INLIST_GET(event));
+   ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE);
+   free(event);
+   events_num--;
+   return data;
+}
+
+static void
+_ecore_event_purge_deleted(void)
+{
+   Ecore_Event *itr = events;
+
+   while (itr)
+     {
+       Ecore_Event *next = (Ecore_Event *)EINA_INLIST_GET(itr)->next;
+       if (!itr->references)
+         _ecore_event_del(itr);
+       itr = next;
+     }
+}
+
+void
+_ecore_event_call(void)
+{
+   Eina_List *l, *l_next;
+   Ecore_Event_Handler *eh;
+
+   if (!event_filter_current)
+     {
+       /* regular main loop, start from head */
+       event_filter_current = event_filters;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
+     }
+
+   while (event_filter_current)
+     {
+       Ecore_Event_Filter *ef = event_filter_current;
+
+       if (!ef->delete_me)
+         {
+            ef->references++;
+
+            if (ef->func_start)
+              ef->loop_data = ef->func_start(ef->data);
+
+            if (!event_current)
+              {
+                 /* regular main loop, start from head */
+                 event_current = events;
+              }
+            else
+              {
+                 /* recursive main loop, continue from where we were */
+                 event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
+              }
+
+            while (event_current)
+              {
+                 Ecore_Event *e = event_current;
+
+                 if (!ef->func_filter(ef->loop_data, ef->data,
+                                      e->type, e->event))
+                   {
+//                    printf("FILTER SAID TO DEL ev %p\n", e->event);
+                      ecore_event_del(e);
+                   }
+
+                 if (event_current) /* may have changed in recursive main loops */
+                   event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
+              }
+            if (ef->func_end)
+              ef->func_end(ef->data, ef->loop_data);
+
+            ef->references--;
+         }
+
+       if (event_filter_current) /* may have changed in recursive main loops */
+         event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
+     }
+   if (event_filters_delete_me)
+     {
+       int deleted_in_use = 0;
+       Ecore_Event_Filter *l;
+       for (l = event_filters; l;)
+         {
+            Ecore_Event_Filter *ef = l;
+            l = (Ecore_Event_Filter *) EINA_INLIST_GET(l)->next;
+            if (ef->delete_me)
+              {
+                 if (ef->references)
+                   {
+                      deleted_in_use++;
+                      continue;
+                   }
+
+                 event_filters = (Ecore_Event_Filter *) eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
+                 ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
+                 free(ef);
+              }
+         }
+       if (!deleted_in_use)
+         event_filters_delete_me = 0;
+     }
+
+//   printf("EVENT BATCH...\n");
+
+   if (!event_current)
+     {
+       /* regular main loop, start from head */
+       event_current = events;
+       event_handler_current = NULL;
+     }
+
+   while (event_current)
+     {
+       Ecore_Event *e = event_current;
+
+       if (!e->delete_me)
+         {
+            int handle_count = 0;
+            ecore_raw_event_type = e->type;
+            ecore_raw_event_event = e->event;
+            e->references++;
+//          printf("HANDLE ev type %i, %p\n", e->type, e->event);
+            if ((e->type >= 0) && (e->type < event_handlers_num))
+              {
+                 if (!event_handler_current)
+                   {
+                      /* regular main loop, start from head */
+                      event_handler_current = event_handlers[e->type];
+                   }
+                 else
+                   {
+                      /* recursive main loop, continue from where we were */
+                      event_handler_current= (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
+                   }
+
+                 while ((event_handler_current) && (!e->delete_me))
+                   {
+                      Ecore_Event_Handler *eh = event_handler_current;
+                      if (!eh->delete_me)
+                        {
+                           int ret;
+
+                           handle_count++;
+
+                           eh->references++;
+                           ret = eh->func(eh->data, e->type, e->event);
+                           eh->references--;
+
+                           if (!ret)
+                             {
+                                event_handler_current = NULL;
+                                break;  /* 0 == "call no further handlers" */
+                             }
+                        }
+                      if (event_handler_current) /* may have changed in recursive main loops */
+                        event_handler_current= (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
+                   }
+              }
+            /* if no handlers were set for EXIT signal - then default is */
+            /* to quit the main loop */
+            if ((e->type == ECORE_EVENT_SIGNAL_EXIT) && (handle_count == 0))
+              ecore_main_loop_quit();
+            e->references--;
+         }
+
+       if (event_current) /* may have changed in recursive main loops */
+         event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
+     }
+//   printf("EVENT BATCH DONE\n");
+   ecore_raw_event_type = ECORE_EVENT_NONE;
+   ecore_raw_event_event = NULL;
+
+   _ecore_event_purge_deleted();
+   EINA_LIST_FOREACH_SAFE(event_handlers_delete_list, l, l_next, eh)
+     {
+       if (eh->references) continue;
+
+       event_handlers_delete_list = eina_list_remove_list(event_handlers_delete_list, l);
+
+       event_handlers[eh->type] = (Ecore_Event_Handler *) eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
+       ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
+       free(eh);
+     }
+}
+
+EAPI void *
+_ecore_event_signal_user_new(void)
+{
+   Ecore_Event_Signal_User *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Signal_User));
+   return e;
+}
+
+void *
+_ecore_event_signal_hup_new(void)
+{
+   Ecore_Event_Signal_Hup *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Signal_Hup));
+   return e;
+}
+
+void *
+_ecore_event_signal_exit_new(void)
+{
+   Ecore_Event_Signal_Exit *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Signal_Exit));
+   return e;
+}
+
+void *
+_ecore_event_signal_power_new(void)
+{
+   Ecore_Event_Signal_Power *e;
+
+   e = calloc(1, sizeof(Ecore_Event_Signal_Power));
+   return e;
+}
+
+void *
+_ecore_event_signal_realtime_new(void)
+{
+   return calloc(1, sizeof(Ecore_Event_Signal_Realtime));
+}
diff --git a/src/lib/ecore/ecore_exe.c b/src/lib/ecore/ecore_exe.c
new file mode 100644 (file)
index 0000000..3366fa6
--- /dev/null
@@ -0,0 +1,1850 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+   /* FIXME: Getting respawn to work
+    *
+    * There is no way that we can do anything about the internal state info of
+    * an external exe.  The same can be said about the state of user code.  User
+    * code in this context means the code that is using ecore_exe to manage exe's
+    * for it.
+    *
+    * Document that the exe must be respawnable, in other words, there is no
+    * state that it cannot regenerate by just killing it and starting it again.
+    * This includes state that the user code knows about, as the respawn is
+    * transparent to that code.  On the other hand, maybe a respawn event might
+    * be useful, or maybe resend the currently non existant add event.  For
+    * consistancy with ecore_con, an add event is good anyway.
+    *
+    * The Ecore_exe structure is reused for respawning, so that the (opaque)
+    * pointer held by the user remains valid.  This means that the Ecore_Exe
+    * init and del functions may need to be split into two parts each to avoid
+    * duplicating code - common code part, and the rest.  This implies that
+    * the unchanging members mentioned next should NEVER change.
+    *
+    * These structure members don't need to change -
+    *   __list_data       - we stay on the list
+    *   ECORE_MAGIC       - this is a constant
+    *   data              - passed in originally
+    *   cmd               - passed in originally
+    *   flags             - passed in originally
+    *
+    * These structure members need to change -
+    *   tag               - state that must be regenerated, zap it
+    *   pid               - it will be different
+    *   child_fd_write    - it will be different
+    *   child_fd_read     - it will be different
+    *   child_fd_error    - it will be different
+    *   write_fd_handler  - we cannot change the fd used by a handler, this changes coz the fd changes.
+    *   read_fd_handler   - we cannot change the fd used by a handler, this changes coz the fd changes.
+    *   error_fd_handler  - we cannot change the fd used by a handler, this changes coz the fd changes.
+    *
+    * Hmm, the read, write, and error buffers could be tricky.
+    * They are not atomic, and could be in a semi complete state.
+    * They fall into the "state must be regenerated" mentioned above.
+    * A respawn/add event should take care of it.
+    *
+    * These structure members need to change -
+    *   write_data_buf    - state that must be regenerated, zap it
+    *   write_data_size   - state that must be regenerated, zap it
+    *   write_data_offset - state that must be regenerated, zap it
+    *   read_data_buf     - state that must be regenerated, zap it
+    *   read_data_size    - state that must be regenerated, zap it
+    *   error_data_buf    - state that must be regenerated, zap it
+    *   error_data_size   - state that must be regenerated, zap it
+    *   close_write       - state that must be regenerated, zap it
+    *
+    * There is the problem that an exe that fell over and needs respawning
+    * might keep falling over, keep needing to be respawned, and tie up system
+    * resources with the constant respawning.  An exponentially increasing
+    * timeout (with maximum timeout) between respawns should take care of that.
+    * Although this is not a "contention for a resource" problem, the exe falling
+    * over may be, so a random element added to the timeout may help, and won't
+    * hurt.  The user code may need to be informed that a timeout is in progress.
+    */
+
+struct _Ecore_Exe
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   pid_t pid;
+   void *data;
+   char *tag, *cmd;
+   Ecore_Exe_Flags  flags;
+   Ecore_Fd_Handler *write_fd_handler; /* the fd_handler to handle write to child - if this was used, or NULL if not */
+   Ecore_Fd_Handler *read_fd_handler; /* the fd_handler to handle read from child - if this was used, or NULL if not */
+   Ecore_Fd_Handler *error_fd_handler; /* the fd_handler to handle errors from child - if this was used, or NULL if not */
+   void  *write_data_buf; /* a data buffer for data to write to the child -
+                                 * realloced as needed for more data and flushed when the fd handler says writes are possible
+                                */
+   int write_data_size; /* the size in bytes of the data buffer */
+   int write_data_offset; /* the offset in bytes in the data buffer */
+   void *read_data_buf; /* data read from the child awating delivery to an event */
+   int read_data_size; /* data read from child in bytes */
+   void *error_data_buf; /* errors read from the child awating delivery to an event */
+   int error_data_size; /* errors read from child in bytes */
+   int child_fd_write; /* fd to write TO to send data to the child */
+   int child_fd_read;  /* fd to read FROM when child has sent us (the parent) data */
+   int child_fd_error; /* fd to read FROM when child has sent us (the parent) errors */
+   int child_fd_write_x;       /* fd to write TO to send data to the child */
+   int child_fd_read_x;        /* fd to read FROM when child has sent us (the parent) data */
+   int child_fd_error_x;       /* fd to read FROM when child has sent us (the parent) errors */
+   Eina_Bool close_stdin : 1;
+
+   int start_bytes, end_bytes, start_lines, end_lines; /* Number of bytes/lines to auto pipe at start/end of stdout/stderr. */
+
+   Ecore_Timer *doomsday_clock; /* The Timer of Death.  Muahahahaha. */
+   void *doomsday_clock_dead; /* data for the doomsday clock */
+
+   void (*pre_free_cb)(void *data, const Ecore_Exe *exe);
+};
+
+
+/* TODO: Something to let people build a command line and does auto escaping -
+ *
+ * ecore_exe_snprintf()
+ *
+ *   OR
+ *
+ * cmd = ecore_exe_comand_parameter_append(cmd, "firefox");
+ * cmd = ecore_exe_comand_parameter_append(cmd, "http://www.foo.com/bar.html?baz=yes");
+ * each parameter appended is one argument, and it gets escaped, quoted, and
+ * appended with a preceeding space.  The first is the command off course.
+ */
+
+struct _ecore_exe_dead_exe
+{
+   pid_t pid;
+   char *cmd;
+};
+
+static inline void _ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags);
+static int _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Exe_Flags flags);
+static int _ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static void _ecore_exe_flush(Ecore_Exe * exe);
+static void _ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev);
+static Ecore_Exe *_ecore_exe_is_it_alive(pid_t pid);
+static int _ecore_exe_make_sure_its_dead(void *data);
+static int _ecore_exe_make_sure_its_really_dead(void *data);
+static Ecore_Exe_Event_Add *_ecore_exe_event_add_new(void);
+static void _ecore_exe_event_add_free(void *data, void *ev);
+static void _ecore_exe_dead_attach(Ecore_Exe *exe);
+
+EAPI int ECORE_EXE_EVENT_ADD = 0;
+EAPI int ECORE_EXE_EVENT_DEL = 0;
+EAPI int ECORE_EXE_EVENT_DATA = 0;
+EAPI int ECORE_EXE_EVENT_ERROR = 0;
+
+static Ecore_Exe *exes = NULL;
+static const char *shell = NULL;
+
+/* FIXME: This errno checking stuff should be put elsewhere for everybody to use.
+ * For now it lives here though, just to make testing easier.
+ */
+static int _ecore_exe_check_errno(int result, const char *file, int line);
+
+#define E_IF_NO_ERRNO(result, foo, ok) \
+  while (((ok) = _ecore_exe_check_errno( (result) = (foo), __FILE__, __LINE__)) == -1)   sleep(1); \
+  if (ok)
+
+#define E_NO_ERRNO(result, foo, ok) \
+  while (((ok) = _ecore_exe_check_errno( (result) = (foo), __FILE__, __LINE__)) == -1)   sleep(1)
+
+#define E_IF_NO_ERRNO_NOLOOP(result, foo, ok) \
+  if (((ok) = _ecore_exe_check_errno( (result) = (foo), __FILE__, __LINE__)))
+
+static int
+_ecore_exe_check_errno(int result, const char *file, int line)
+{
+   int saved_errno = errno;
+
+   if (result == -1)
+     {
+       perror("*** errno reports ");
+/* What is currently supported -
+ *
+ *   pipe
+ *     EFAULT  Argument is not valid.
+ *     EMFILE  Too many file descriptors used by process.
+ *     ENFILE  Too many open files by system.
+ *   read
+ *     EAGAIN  No data now, try again.
+ *     EBADF   This is not an fd that can be read.
+ *     EFAULT  This is not a valid buffer.
+ *     EINTR   Interupted by signal, try again.
+ *     EINVAL  This is not an fd that can be read.
+ *     EIO     I/O error.
+ *     EISDIR  This is a directory, and cannot be read.
+ *     others  Depending on what sort of thing we are reading from.
+ *   close
+ *     EBADF   This is not an fd that can be closed.
+ *     EINTR   Interupted by signal, try again.
+ *     EIO     I/O error.
+ *   dup2
+ *     EBADF   This is not an fd that can be dup2'ed.
+ *     EBUSY   Race condition between open() and dup()
+ *     EINTR   Interupted by signal, try again.
+ *     EMFILE  Too many file descriptors used by process.
+ *   fcntl
+ *     EACCES, EAGAIN  Locked or mapped by something else, try again later.
+ *     EBADF   This is not an fd that can be fcntl'ed.
+ *     EDEADLK This will cause a deadlock.
+ *     EFAULT  This is not a valid lock.
+ *     EINTR   Interupted by signal, try again.
+ *     EINVAL  This is not a valid arg.
+ *     EMFILE  Too many file descriptors used by process.
+ *     ENOLCK  Problem getting a lock.
+ *     EPERM   Not allowed to do that.
+ *   fsync
+ *     EBADF   This is not an fd that is open for writing.
+ *     EINVAL, EROFS  This is not an fd that can be fsynced.
+ *     EIO     I/O error.
+ *
+ * How to use it -
+ *    int ok = 0;
+ *    int result;
+ *
+ *    E_IF_NO_ERRNO(result, foo(bar), ok)
+ *      {
+ *         E_IF_NO_ERRNO_NOLOOP(result, foo(bar), ok)
+ *            {
+ *            }
+ *      }
+ *
+ *   if (!ok)
+ *     {
+ *        // Something failed, cleanup.
+ *     }
+ */
+       switch (saved_errno)
+         {
+           case EACCES:
+           case EAGAIN:
+           case EINTR:
+               { /* Not now, try later. */
+                  ERR("*** Must try again in %s @%u.", file, line);
+                  result = -1;
+                  break;
+               }
+           case EMFILE:
+           case ENFILE:
+           case ENOLCK:
+               { /* Low on resources. */
+                  ERR("*** Low on resources in %s @%u.", file,
+                      line);
+                  result = 0;
+                  break;
+               }
+           case EIO:
+               { /* I/O error. */
+                  ERR("*** I/O error in %s @%u.", file, line);
+                  result = 0;
+                  break;
+               }
+           case EFAULT:
+           case EBADF:
+           case EINVAL:
+           case EROFS:
+           case EISDIR:
+           case EDEADLK:
+           case EPERM:
+           case EBUSY:
+               { /* Programmer fucked up. */
+                  ERR("*** NAUGHTY PROGRAMMER!!!\n"
+                      "*** SPANK SPANK SPANK!!!\n"
+                      "*** Now go fix your code in %s @%u. Tut tut tut!",
+                      file, line);
+                  result = 0;
+                  break;
+               }
+           default:
+               { /* Unsupported errno code, please add this one. */
+                  ERR("*** NAUGHTY PROGRAMMER!!!\n"
+                      "*** SPANK SPANK SPANK!!!\n"
+                      "*** Unsupported errno code %d, please add this one.\n"
+                      "*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!",
+                      saved_errno, __FILE__, __LINE__, file, line);
+                  result = 0;
+                  break;
+               }
+         }
+     }
+   else /* Everything is fine. */
+     result = 1;
+
+   errno = saved_errno;
+   return result;
+}
+
+/**
+ * @defgroup Ecore_Exe_Basic_Group Process Spawning Functions
+ *
+ * Functions that deal with spawned processes.
+ */
+
+static int run_pri = ECORE_EXE_PRIORITY_INHERIT;
+
+/**
+ * Sets the priority at which to launch processes
+ *
+ * This sets the priority of processes run by ecore_exe_run() and
+ * ecore_exe_pipe_run().
+ * @li On Windows, the child process is created by default with the
+ * #ECORE_EXE_WIN32_PRIORITY_NORMAL priority, unless the calling
+ * process is in #ECORE_EXE_WIN32_PRIORITY_IDLE or
+ * #ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL priority. In that case, the
+ * child process inherits this priority.
+ * @li On other platforms, if set to #ECORE_EXE_PRIORITY_INHERIT child
+ * processes inherits the priority of their parent. This is the default.
+ *
+ * @param   pri value a Ecore_Exe_Win32_Priority value on Windows, -20
+ * to 19 or ECORE_EXE_PRIORITY_INHERIT on other OS.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void
+ecore_exe_run_priority_set(int pri)
+{
+   run_pri = pri;
+}
+
+/**
+ * Gets the priority at which to launch processes
+ *
+ * This gets ths priority of launched processes. See
+ * ecore_exe_run_priority_set() for details. This just returns the value set
+ * by this call.
+ *
+ * @return the value set by ecore_exe_run_priority_set()
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI int
+ecore_exe_run_priority_get(void)
+{
+   return run_pri;
+}
+
+/**
+ * Spawns a child process.
+ *
+ * This is now just a thin wrapper around ecore_exe_pipe_run()
+ *
+ * @param   exe_cmd The command to run with @c /bin/sh.
+ * @param   data    Data to attach to the returned process handle.
+ * @return  A process handle to the spawned process.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI Ecore_Exe *
+ecore_exe_run(const char *exe_cmd, const void *data)
+{
+/* I'm just being paranoid again, leaving in the original code in case there is a problem. */
+#if 0
+   Ecore_Exe *exe;
+   pid_t pid;
+
+   if (!exe_cmd)
+      return NULL;
+   pid = fork();
+   if (pid)
+     {
+       exe = calloc(1, sizeof(Ecore_Exe));
+       if (!exe)
+         {
+            kill(pid, SIGKILL);
+            return NULL;
+         }
+       ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
+       exe->pid = pid;
+       exe->data = (void *)data;
+       exe->cmd = strdup(exe_cmd);
+       exes = _ecore_list2_append(exes, exe);
+       return exe;
+     }
+   _ecore_exe_exec_it(exe_cmd, 0);
+   exit(127);
+   return NULL;
+#else
+   return ecore_exe_pipe_run(exe_cmd, 0, data);
+#endif
+}
+
+/**
+ * Spawns a child process with its stdin/out available for communication.
+ *
+ * This function forks and runs the given command using @c /bin/sh.
+ *
+ * Note that the process handle is only valid until a child process
+ * terminated event is received.  After all handlers for the child process
+ * terminated event have been called, the handle will be freed by Ecore.
+ *
+ * This function does the same thing as ecore_exe_run(), but also makes the
+ * standard in and/or out as well as stderr from the child process available
+ * for reading or writing.  To write use ecore_exe_send().  To read listen to
+ * ECORE_EXE_EVENT_DATA or ECORE_EXE_EVENT_ERROR events (set up handlers).
+ * Ecore may buffer read and error data until a newline character if asked
+ * for with the @p flags.  All data will be included in the events (newlines
+ * will be replaced with NULLS if line buffered).  ECORE_EXE_EVENT_DATA events
+ * will only happen if the process is run with ECORE_EXE_PIPE_READ enabled
+ * in the flags.  The same with the error version.  Writing will only be
+ * allowed with ECORE_EXE_PIPE_WRITE enabled in the flags.
+ *
+ * @param   exe_cmd The command to run with @c /bin/sh.
+ * @param   flags   The flag parameters for how to deal with inter-process I/O
+ * @param   data    Data to attach to the returned process handle.
+ * @return  A process handle to the spawned process.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI Ecore_Exe *
+ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
+{
+   Ecore_Exe *exe = NULL;
+   int statusPipe[2] = { -1, -1 };
+   int errorPipe[2] = { -1, -1 };
+   int readPipe[2] = { -1, -1 };
+   int writePipe[2] = { -1, -1 };
+   int n = 0;
+   int ok = 1;
+   int result;
+
+   if (!exe_cmd) return NULL;
+   exe = calloc(1, sizeof(Ecore_Exe));
+   if (exe == NULL) return NULL;
+
+   if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))
+       && (!(flags & ECORE_EXE_PIPE_READ)))
+     /* We need something to auto pipe. */
+     flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
+
+   exe->child_fd_error = -1;
+   exe->child_fd_read = -1;
+   exe->child_fd_write = -1;
+   exe->child_fd_error_x = -1;
+   exe->child_fd_read_x = -1;
+   exe->child_fd_write_x = -1;
+
+   /*  Create some pipes. */
+   if (ok)
+     {
+       E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok)
+         {
+         }
+     }
+   if (ok && (flags & ECORE_EXE_PIPE_ERROR))
+     {
+       E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok)
+         {
+            exe->child_fd_error = errorPipe[0];
+            exe->child_fd_error_x = errorPipe[1];
+         }
+     }
+   if (ok && (flags & ECORE_EXE_PIPE_READ))
+     {
+       E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok)
+         {
+            exe->child_fd_read = readPipe[0];
+            exe->child_fd_read_x = readPipe[1];
+         }
+     }
+   if (ok && (flags & ECORE_EXE_PIPE_WRITE))
+     {
+       E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok)
+         {
+            exe->child_fd_write = writePipe[1];
+            exe->child_fd_write_x = writePipe[0];
+         }
+     }
+   if (ok)
+     {
+       pid_t pid = 0;
+       volatile int vfork_exec_errno = 0;
+
+       /* FIXME: I should double check this.  After a quick look around, this is already done, but via a more modern method. */
+       /* signal(SIGPIPE, SIG_IGN);    We only want EPIPE on errors */
+       pid = fork();
+
+       if (pid == -1)
+         {
+            ERR("Failed to fork process");
+            pid = 0;
+         }
+       else if (pid == 0)      /* child */
+         {
+            if (run_pri != ECORE_EXE_PRIORITY_INHERIT)
+              {
+                 if ((run_pri >= -20) && (run_pri <= 19))
+                    setpriority(PRIO_PROCESS, 0, run_pri);
+              }
+            /* dup2 STDERR, STDIN, and STDOUT.  dup2() allegedly closes the
+             * second pipe if it's open. On the other hand, there was the
+             * Great FD Leak Scare of '06, so let's be paranoid. */
+            if (ok && (flags & ECORE_EXE_PIPE_ERROR))
+              {
+                 E_NO_ERRNO(result, close(STDERR_FILENO), ok);
+                 E_NO_ERRNO(result, dup2(errorPipe[1], STDERR_FILENO), ok);
+              }
+            if (ok && (flags & ECORE_EXE_PIPE_READ))
+              {
+                 E_NO_ERRNO(result, close(STDOUT_FILENO), ok);
+                 E_NO_ERRNO(result, dup2(readPipe[1], STDOUT_FILENO), ok);
+              }
+            if (ok && (flags & ECORE_EXE_PIPE_WRITE))
+              {
+                 E_NO_ERRNO(result, close(STDIN_FILENO), ok);
+                 E_NO_ERRNO(result, dup2(writePipe[0], STDIN_FILENO), ok);
+              }
+
+            if (ok)
+              {
+                 /* Setup the status pipe. */
+                 E_NO_ERRNO(result, close(statusPipe[0]), ok);
+                 E_IF_NO_ERRNO(result, fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC), ok)  /* close on exec shows sucess */
+                   {
+                      /* Run the actual command. */
+                      _ecore_exe_exec_it(exe_cmd, flags); /* no return */
+                   }
+              }
+
+            /* Something went 'orribly wrong. */
+            vfork_exec_errno = errno;
+
+            /* Close the pipes. */
+            if (flags & ECORE_EXE_PIPE_ERROR)
+              E_NO_ERRNO(result, close(errorPipe[1]), ok);
+            if (flags & ECORE_EXE_PIPE_READ)
+              E_NO_ERRNO(result, close(readPipe[1]), ok);
+            if (flags & ECORE_EXE_PIPE_WRITE)
+              E_NO_ERRNO(result, close(writePipe[0]), ok);
+            E_NO_ERRNO(result, close(statusPipe[1]), ok);
+
+            _exit(-1);
+         }
+       else /* parent */
+         {
+            /* Close the unused pipes. */
+            E_NO_ERRNO(result, close(statusPipe[1]), ok);
+
+            /* FIXME: after having a good look at the current e fd
+             * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */
+            /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO
+             * which is also linux specific so we probably don't want to
+             * do this as long as select() is working fine. the only time
+             * we really want to think of SIGIO async IO is when it all
+             * actually works basically everywhere and we can turn all
+             * IO into DMA async activities (i.e. you do a read() then
+             * the read is complete not on return but when you get a
+             * SIGIO - the read() just starts the transfer and it is
+             * completed in the background by DMA (or whatever mechanism
+             * the kernel choses)) */
+
+            /* Wait for it to start executing. */
+            /* FIXME: this doesn't seem very nice - we sit and block
+             * waiting on a child process... even though it's just
+             * the segment between the fork() and the exec) it just feels
+             * wrong */
+            for (;;)
+              {
+                 char buf;
+
+                 E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok);
+                 if (result == 0)
+                   {
+                      if (vfork_exec_errno != 0)
+                        {
+                           n = vfork_exec_errno;
+                           ERR("Could not start \"%s\"", exe_cmd);
+                           pid = 0;
+                        }
+                      break;
+                   }
+              }
+
+            /* Close the status pipe. */
+            E_NO_ERRNO(result, close(statusPipe[0]), ok);
+         }
+
+       if (pid)
+         {
+            /* Setup the exe structure. */
+            ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
+            exe->start_bytes = -1;
+            exe->end_bytes = -1;
+            exe->start_lines = -1;
+            exe->end_lines = -1;
+            exe->pid = pid;
+            exe->flags = flags;
+            exe->data = (void *)data;
+            if ((exe->cmd = strdup(exe_cmd)))
+              {
+                 if (flags & ECORE_EXE_PIPE_ERROR)
+                   { /* Setup the error stuff. */
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_error, F_SETFL,
+                                          O_NONBLOCK), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_error, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_error_x, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      {
+                         exe->error_fd_handler =
+                            ecore_main_fd_handler_add(exe->child_fd_error,
+                                                      ECORE_FD_READ,
+                                                      _ecore_exe_data_error_handler,
+                                                      exe, NULL, NULL);
+                         if (exe->error_fd_handler == NULL)
+                            ok = 0;
+                      }
+                   }
+                 if (ok && (flags & ECORE_EXE_PIPE_READ))
+                   { /* Setup the read stuff. */
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_read, F_SETFL,
+                                          O_NONBLOCK), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_read, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_read_x, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      {
+                         exe->read_fd_handler =
+                            ecore_main_fd_handler_add(exe->child_fd_read,
+                                                      ECORE_FD_READ,
+                                                      _ecore_exe_data_read_handler,
+                                                      exe, NULL, NULL);
+                         if (exe->read_fd_handler == NULL)
+                            ok = 0;
+                      }
+                   }
+                 if (ok && (flags & ECORE_EXE_PIPE_WRITE))
+                   {           /* Setup the write stuff. */
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_write, F_SETFL,
+                                          O_NONBLOCK), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_write, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      E_IF_NO_ERRNO(result,
+                                    fcntl(exe->child_fd_write_x, F_SETFD,
+                                          FD_CLOEXEC), ok) {}
+                      {
+                         exe->write_fd_handler =
+                            ecore_main_fd_handler_add(exe->child_fd_write,
+                                                      ECORE_FD_WRITE,
+                                                      _ecore_exe_data_write_handler,
+                                                      exe, NULL, NULL);
+                         if (exe->write_fd_handler)
+                            ecore_main_fd_handler_active_set(exe->write_fd_handler, 0);        /* Nothing to write to start with. */
+                         else
+                            ok = 0;
+                      }
+                   }
+
+                 exes = (Ecore_Exe *) eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+                 n = 0;
+              }
+            else
+              ok = 0;
+         }
+       else
+         ok = 0;
+     }
+
+   if (!ok)
+     { /* Something went wrong, so pull down everything. */
+       if (exe->pid) ecore_exe_terminate(exe);
+       IF_FN_DEL(ecore_exe_free, exe);
+     }
+   else
+     {
+       Ecore_Exe_Event_Add *e;
+
+       e = _ecore_exe_event_add_new();
+       e->exe = exe;
+       if (e) /* Send the event. */
+         ecore_event_add(ECORE_EXE_EVENT_ADD, e,
+                         _ecore_exe_event_add_free, NULL);
+       /* INF("Running as %d for %s.\n", exe->pid, exe->cmd); */
+     }
+
+   errno = n;
+   return exe;
+}
+
+/**
+ * Defines a function to be called before really freeing the handle data.
+ *
+ * This might be useful for language bindings such as Python and Perl
+ * that need to deallocate wrappers associated with this handle.
+ *
+ * This handle should never be modified by this call. It should be
+ * considered informative only. All getters are valid when the given
+ * function is called back.
+ *
+ * @param exe The child process to attach the pre_free function.
+ * @param func The function to call before @a exe is freed.
+ */
+EAPI void
+ecore_exe_callback_pre_free_set(Ecore_Exe *exe, void (*func)(void *data, const Ecore_Exe *exe))
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+                        "ecore_exe_callback_pre_free_set");
+       return;
+     }
+   exe->pre_free_cb = func;
+}
+
+/**
+ * Sends data to the given child process which it recieves on stdin.
+ *
+ * This function writes to a child processes standard in, with unlimited
+ * buffering. This call will never block. It may fail if the system runs out
+ * of memory.
+ *
+ * @param exe  The child process to send to
+ * @param data The data to send
+ * @param size The size of the data to send, in bytes
+ * @return EINA_TRUE if successful, EINA_FALSE on failure.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI Eina_Bool
+ecore_exe_send(Ecore_Exe * exe, const void *data, int size)
+{
+   void *buf;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_send");
+       return 0;
+     }
+
+   if (exe->close_stdin)
+     {
+       ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
+           exe, size, data);
+       return 0;
+     }
+
+   if (exe->child_fd_write == -1)
+     {
+       ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! "
+           "Cannot send %d bytes from %p", exe, size, data);
+       return 0;
+     }
+
+   buf = realloc(exe->write_data_buf, exe->write_data_size + size);
+   if (buf == NULL) return 0;
+
+   exe->write_data_buf = buf;
+   memcpy((char *)exe->write_data_buf + exe->write_data_size, data, size);
+   exe->write_data_size += size;
+
+   if (exe->write_fd_handler)
+      ecore_main_fd_handler_active_set(exe->write_fd_handler, ECORE_FD_WRITE);
+
+   return 1;
+}
+
+/**
+ * The stdin of the given child process will close when the write buffer is empty.
+ *
+ * @param exe  The child process
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void
+ecore_exe_close_stdin(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_close_stdin");
+       return;
+     }
+   exe->close_stdin = 1;
+}
+
+/**
+ * Sets the auto pipe limits for the given process handle. On Windows
+ * this function does nothing.
+ *
+ * @param   exe The given process handle.
+ * @param   start_bytes limit of bytes at start of output to buffer.
+ * @param   end_bytes limit of bytes at end of output to buffer.
+ * @param   start_lines limit of lines at start of output to buffer.
+ * @param   end_lines limit of lines at end of output to buffer.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void
+ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_auto_limits_set");
+       return;
+     }
+   /* FIXME: sanitize the input. */
+   exe->start_bytes = start_bytes;
+   exe->end_bytes = end_bytes;
+   exe->start_lines = start_lines;
+   exe->end_lines = end_lines;
+
+   /* FIXME: get this can of worms working.
+    *
+    * capture stderr & stdout internally
+    *
+    * raster and onefang keep moving the goal posts on this one.  It started out as
+    * "show users the error output if an exe fails" and is rapidly approaching
+    * "alternative method of getting the data, poll vs event driven".  Some serious
+    * thinking needs to be applied to this.  Do we really want to go that far?  If
+    * so, we should change the names.  The basic design will probably remain the
+    * same which ever way we go.  The constant goal post moving is probably due to
+    * generic design methods leading to feature creep as we inspired each other to
+    * more generic designs.  It does seem like the closer we get to poll driven,
+    * the more issues and corner cases there are.
+    *
+    * Instead of doing the usual register an event handler thing, we are ecore_exe,
+    * we can take some short cuts.  Don't send the events, just leave the exe buffers
+    * as is until the user asks for them, then return the event.
+    *
+    * start = 0,  end = 0;   clogged arteries get flushed, everything is ignored.
+    * start = -1, end = -1;  clogged arteries get transferred to internal buffers.  Actually, either == -1 means buffer everything.
+    * start = X,  end = 0;   buffer first X out of clogged arteries, flush and ignore rest.
+    * start = 0,  end = X;   circular buffer X
+    * start = X,  end = Y;   buffer first X out of clogged arteries, circular buffer Y from beginning.
+    *
+    * bytes vs lines, which ever one reaches the limit first.
+    * Before we go beyond the start+end limit, leave the end buffer empty, and store both in the start buffer, coz they overlap.
+    * After we pass the the start+end limit, insert "\n...\n" at the end of the start buffer, copy the rest to the end buffer, then store in the end buffer.
+    *
+    * Other issues -
+    * Spank programmer for polling data if polling is not turned on.
+    * Spank programmer for setting up event callbacks if polling is turned on.
+    * Spank programmer for freeing the event data if it came from the event system, as that autofrees.
+    * Spank the programmer if they try to set the limits bigger than what has been gathered & ignored already, coz they just lost data.
+    * Spank onefang and raster for opening this can of worms.
+    * Should we have seperate out/err limits?
+    * Should we remove from the internal buffer the data that was delivered already?
+    * If so, what to do about limits, start, and end?  They could loose their meaning.
+    */
+}
+
+/**
+ * Gets the auto pipe data for the given process handle
+ *
+ * @param   exe The given process handle.
+ * @param   flags   Is this a ECORE_EXE_PIPE_READ or ECORE_EXE_PIPE_ERROR?
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI Ecore_Exe_Event_Data *
+ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
+{
+   Ecore_Exe_Event_Data *e = NULL;
+   int is_buffered = 0;
+   unsigned char *inbuf;
+   int inbuf_num;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_event_data_get");
+       return NULL;
+     }
+
+   /* Sort out what sort of event we are. */
+   if (flags & ECORE_EXE_PIPE_READ)
+     {
+       flags = ECORE_EXE_PIPE_READ;
+       if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
+          is_buffered = 1;
+     }
+   else
+     {
+       flags = ECORE_EXE_PIPE_ERROR;
+       if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
+          is_buffered = 1;
+     }
+
+   /* Get the data. */
+   if (flags & ECORE_EXE_PIPE_READ)
+     {
+       inbuf = exe->read_data_buf;
+       inbuf_num = exe->read_data_size;
+       exe->read_data_buf = NULL;
+       exe->read_data_size = 0;
+     }
+   else
+     {
+       inbuf = exe->error_data_buf;
+       inbuf_num = exe->error_data_size;
+       exe->error_data_buf = NULL;
+       exe->error_data_size = 0;
+     }
+
+   e = calloc(1, sizeof(Ecore_Exe_Event_Data));
+   if (e)
+     {
+       e->exe = exe;
+       e->data = inbuf;
+       e->size = inbuf_num;
+
+       if (is_buffered)
+         {                     /* Deal with line buffering. */
+            int max = 0;
+            int count = 0;
+            int i;
+            int last = 0;
+            char *c;
+
+            c = (char *)inbuf;
+            for (i = 0; i < inbuf_num; i++)    /* Find the lines. */
+              {
+                 if (inbuf[i] == '\n')
+                   {
+                      if (count >= max)
+                        {
+                           /* In testing, the lines seem to arrive in batches of 500 to 1000 lines at most, roughly speaking. */
+                           max += 10;  /* FIXME: Maybe keep track of the largest number of lines ever sent, and add half that many instead of 10. */
+                           e->lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1));        /* Allow room for the NULL termination. */
+                        }
+                      /* raster said to leave the line endings as line endings, however -
+                       * This is line buffered mode, we are not dealing with binary here, but lines.
+                       * If we are not dealing with binary, we must be dealing with ASCII, unicode, or some other text format.
+                       * Thus the user is most likely gonna deal with this text as strings.
+                       * Thus the user is most likely gonna pass this data to str functions.
+                       * rasters way - the endings are always gonna be '\n';  onefangs way - they will always be '\0'
+                       * We are handing them the string length as a convenience.
+                       * Thus if they really want it in raw format, they can e->lines[i].line[e->lines[i].size - 1] = '\n'; easily enough.
+                       * In the default case, we can do this conversion quicker than the user can, as we already have the index and pointer.
+                       * Let's make it easy on them to use these as standard C strings.
+                       *
+                       * onefang is proud to announce that he has just set a new personal record for the
+                       * most over documentation of a simple assignment statement.  B-)
+                       */
+                      inbuf[i] = '\0';
+                      e->lines[count].line = c;
+                      e->lines[count].size = i - last;
+                      last = i + 1;
+                      c = (char *)&inbuf[last];
+                      count++;
+                   }
+              }
+            if (count == 0)    /* No lines to send, cancel the event. */
+              {
+                 _ecore_exe_event_exe_data_free(NULL, e);
+                 e = NULL;
+              }
+            else               /* NULL terminate the array, so that people know where the end is. */
+              {
+                 e->lines[count].line = NULL;
+                 e->lines[count].size = 0;
+              }
+            if (i > last)      /* Partial line left over, save it for next time. */
+              {
+                 if (e) e->size = last;
+                 if (flags & ECORE_EXE_PIPE_READ)
+                   {
+                      exe->read_data_size = i - last;
+                      exe->read_data_buf = malloc(exe->read_data_size);
+                      memcpy(exe->read_data_buf, c, exe->read_data_size);
+                   }
+                 else
+                   {
+                      exe->error_data_size = i - last;
+                      exe->error_data_buf = malloc(exe->error_data_size);
+                      memcpy(exe->error_data_buf, c, exe->error_data_size);
+                   }
+              }
+         }
+     }
+
+   return e;
+}
+
+/**
+ * Sets the string tag for the given process handle
+ *
+ * @param   exe The given process handle.
+ * @param   tag The string tag to set on the process handle.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void
+ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set");
+       return;
+     }
+   IF_FREE(exe->tag);
+   if (tag)
+      exe->tag = strdup(tag);
+   else
+      exe->tag = NULL;
+}
+
+/**
+ * Retrieves the tag attached to the given process handle. There is no need to
+ * free it as it just returns the internal pointer value. This value is only
+ * valid as long as the @p exe is valid or until the tag is set to something
+ * else on this @p exe.
+ *
+ * @param   exe The given process handle.
+ * @return The string attached to @p exe. It is a handle to existing
+ *         internal string and should not be modified, use
+ *         ecore_exe_tag_set() to change it. It might be @c NULL.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI const char *
+ecore_exe_tag_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get");
+       return NULL;
+     }
+   return exe->tag;
+}
+
+/**
+ * Frees the given process handle.
+ *
+ * Note that the process that the handle represents is unaffected by this
+ * function.
+ *
+ * @param   exe The given process handle.
+ * @return  The data attached to the handle when @ref ecore_exe_run was
+ *          called.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void *
+ecore_exe_free(Ecore_Exe *exe)
+{
+   void *data;
+   int ok = 0;
+   int result;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
+       return NULL;
+     }
+
+   data = exe->data;
+
+   if (exe->pre_free_cb)
+     exe->pre_free_cb(data, exe);
+
+   if (exe->doomsday_clock)
+     {
+       struct _ecore_exe_dead_exe *dead;
+
+       ecore_timer_del(exe->doomsday_clock);
+       exe->doomsday_clock = NULL;
+       dead = exe->doomsday_clock_dead;
+       if (dead)
+         {
+            IF_FREE(dead->cmd);
+            free(dead);
+            exe->doomsday_clock_dead = NULL;
+         }
+     }
+   IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
+   IF_FN_DEL(ecore_main_fd_handler_del, exe->read_fd_handler);
+   IF_FN_DEL(ecore_main_fd_handler_del, exe->error_fd_handler);
+   if (exe->child_fd_write_x != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_write_x), ok);
+   if (exe->child_fd_read_x != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_read_x), ok);
+   if (exe->child_fd_error_x != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_error_x), ok);
+   if (exe->child_fd_write != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_write), ok);
+   if (exe->child_fd_read != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_read), ok);
+   if (exe->child_fd_error != -1)
+      E_NO_ERRNO(result, close(exe->child_fd_error), ok);
+   IF_FREE(exe->write_data_buf);
+   IF_FREE(exe->read_data_buf);
+   IF_FREE(exe->error_data_buf);
+   IF_FREE(exe->cmd);
+
+   exes = (Ecore_Exe *) eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+   ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
+   IF_FREE(exe->tag);
+   free(exe);
+   return data;
+}
+
+/**
+ * Frees the given event data.
+ *
+ * @param   e The given event data.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void
+ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
+{
+   if (!e) return;
+   IF_FREE(e->lines);
+   IF_FREE(e->data);
+   free(e);
+}
+
+/**
+ * Retrieves the process ID of the given spawned process.
+ * @param   exe Handle to the given spawned process.
+ * @return  The process ID on success.  @c -1 otherwise.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI pid_t
+ecore_exe_pid_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get");
+       return -1;
+     }
+   return exe->pid;
+}
+
+/**
+ * Retrieves the command of the given spawned process.
+ * @param   exe Handle to the given spawned process.
+ * @return The command on success.  NULL otherwise. This string is the
+ *         pointer to the internal value and must not be modified in
+ *         any way.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI const char *
+ecore_exe_cmd_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get");
+       return NULL;
+     }
+   return exe->cmd;
+}
+
+/**
+ * Retrieves the data attached to the given process handle.
+ * @param   exe The given process handle.
+ * @return The data pointer attached to @p exe Given to
+ *         ecore_exe_run() or ecore_exe_pipe_run()
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI void *
+ecore_exe_data_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
+       return NULL;
+     }
+   return exe->data;
+}
+
+/**
+ * Retrieves the flags attached to the given process handle.
+ * @param   exe The given process handle.
+ * @return  The flags attached to @p exe.
+ * @ingroup Ecore_Exe_Basic_Group
+ */
+EAPI Ecore_Exe_Flags
+ecore_exe_flags_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
+       return 0;
+     }
+   return exe->flags;
+}
+
+/**
+ * @defgroup Ecore_Exe_Signal_Group Spawned Process Signal Functions
+ *
+ * Functions that send signals to spawned processes.
+ */
+
+/**
+ * Pauses the given process by sending it a @c SIGSTOP signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_pause(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
+       return;
+     }
+   kill(exe->pid, SIGSTOP);
+}
+
+/**
+ * Continues the given paused process by sending it a @c SIGCONT signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_continue(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue");
+       return;
+     }
+   kill(exe->pid, SIGCONT);
+}
+
+/**
+ * Sends the given spawned process a interrupt (@c SIGINT) signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_interrupt(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt");
+       return;
+     }
+   _ecore_exe_dead_attach(exe);
+   kill(exe->pid, SIGINT);
+}
+
+/**
+ * Sends the given spawned process a quit (@c SIGQUIT) signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_quit(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
+       return;
+     }
+   _ecore_exe_dead_attach(exe);
+   kill(exe->pid, SIGQUIT);
+}
+
+/**
+ * Sends the given spawned process a terminate (@c SIGTERM) signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_terminate(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate");
+       return;
+     }
+   _ecore_exe_dead_attach(exe);
+   INF("Sending TERM signal to %s (%d).", exe->cmd, exe->pid);
+   kill(exe->pid, SIGTERM);
+}
+
+/**
+ * Kills the given spawned process by sending it a @c SIGKILL signal.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_kill(Ecore_Exe *exe)
+{
+   struct _ecore_exe_dead_exe *dead;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
+       return;
+     }
+
+   dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
+   if (dead)
+     {
+       dead->pid = exe->pid;
+       dead->cmd = strdup(exe->cmd);
+       IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
+       exe->doomsday_clock =
+          ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, dead);
+     }
+
+   INF("Sending KILL signal to %s (%d).", exe->cmd, exe->pid);
+   kill(exe->pid, SIGKILL);
+}
+
+/**
+ * Sends a @c SIGUSR signal to the given spawned process.
+ * @param   exe Process handle to the given process.
+ * @param   num The number user signal to send.  Must be either 1 or 2, or
+ *              the signal will be ignored.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_signal(Ecore_Exe *exe, int num)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
+       return;
+     }
+   if (num == 1)
+      kill(exe->pid, SIGUSR1);
+   else if (num == 2)
+      kill(exe->pid, SIGUSR2);
+}
+
+/**
+ * Sends a @c SIGHUP signal to the given spawned process.
+ * @param   exe Process handle to the given process.
+ * @ingroup Ecore_Exe_Signal_Group
+ */
+EAPI void
+ecore_exe_hup(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
+       return;
+     }
+   kill(exe->pid, SIGHUP);
+}
+
+static Ecore_Exe *
+_ecore_exe_is_it_alive(pid_t pid)
+{
+   Ecore_Exe *exe = NULL;
+
+   /* FIXME: There is no nice, safe, OS independant way to tell if a
+    * particular PID is still alive.  I have written code to do so
+    * for my urunlevel busybox applet (http://urunlevel.sourceforge.net/),
+    * but it's for linux only, and still not guaranteed.
+    *
+    * So for now, we just check that a valid Ecore_Exe structure
+    * exists for it.  Even that is not a guarantee, as the structure
+    * can be freed without killing the process.
+    *
+    * I think we can safely put exe's into two categories, those users
+    * that care about the life of the exe, and the run and forget type.
+    * The run and forget type starts up the exe, then free's the
+    * Ecore_Exe structure straight away.  They can never call any of
+    * the functions that can call this, so we don't worry about them.
+    *
+    * Those user's that care about the life of exe's will keep the
+    * Ecore_Exe structure around, terminate them eventually, or
+    * register for exit events.  For these ones the assumption
+    * that valid Ecore_Exe struct == live exe is almost valid.
+    *
+    * I will probably copy my urunlevel code into here someday.
+    */
+   exe = _ecore_exe_find(pid);
+   if (exe)
+     {
+       if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+          exe = NULL;
+     }
+
+   return exe;
+}
+
+static int
+_ecore_exe_make_sure_its_dead(void *data)
+{
+   struct _ecore_exe_dead_exe *dead;
+
+   dead = data;
+   if (dead)
+     {
+       Ecore_Exe *exe = NULL;
+
+       if ((exe = _ecore_exe_is_it_alive(dead->pid)) != NULL)
+         {
+            if (dead->cmd)
+               INF("Sending KILL signal to alledgedly dead %s (%d).",
+                      dead->cmd, dead->pid);
+            else
+               INF("Sending KILL signal to alledgedly dead PID %d.",
+                   dead->pid);
+            exe->doomsday_clock =
+               ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead,
+                               dead);
+            kill(dead->pid, SIGKILL);
+         }
+       else
+         {
+            IF_FREE(dead->cmd);
+            free(dead);
+         }
+     }
+   return 0;
+}
+
+static int
+_ecore_exe_make_sure_its_really_dead(void *data)
+{
+   struct _ecore_exe_dead_exe *dead;
+
+   dead = data;
+   if (dead)
+     {
+       Ecore_Exe *exe = NULL;
+
+       if ((exe = _ecore_exe_is_it_alive(dead->pid)) != NULL)
+         {
+            ERR("RUN!  The zombie wants to eat your brains!  And your CPU!");
+            if (dead->cmd)
+               INF("%s (%d) is not really dead.", dead->cmd, dead->pid);
+            else
+               INF("PID %d is not really dead.", dead->pid);
+            exe->doomsday_clock = NULL;
+         }
+       IF_FREE(dead->cmd);
+       free(dead);
+     }
+   return 0;
+}
+
+void
+_ecore_exe_init(void)
+{
+   ECORE_EXE_EVENT_ADD = ecore_event_type_new();
+   ECORE_EXE_EVENT_DEL = ecore_event_type_new();
+   ECORE_EXE_EVENT_DATA = ecore_event_type_new();
+   ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
+}
+
+void
+_ecore_exe_shutdown(void)
+{
+   while (exes)
+     ecore_exe_free(exes);
+}
+
+Ecore_Exe *
+_ecore_exe_find(pid_t pid)
+{
+   Ecore_Exe *exe;
+
+   EINA_INLIST_FOREACH(exes, exe)
+     {
+       if (exe->pid == pid)
+          return exe;
+     }
+   return NULL;
+}
+
+Ecore_Timer *
+_ecore_exe_doomsday_clock_get(Ecore_Exe *exe)
+{
+   return exe->doomsday_clock;
+}
+
+void
+_ecore_exe_doomsday_clock_set(Ecore_Exe *exe, Ecore_Timer *dc)
+{
+   exe->doomsday_clock = dc;
+}
+
+static inline void
+_ecore_exe_exec_it(const char *exe_cmd, Ecore_Exe_Flags flags)
+{
+   char use_sh = 1;
+   char *buf = NULL;
+   char **args = NULL;
+   int  save_errno = 0;
+
+   /* So what is this doing?
+    *
+    * We are trying to avoid wrapping the exe call with /bin/sh -c.
+    * We conservatively search for certain shell meta characters,
+    * If we don't find them, we can call the exe directly.
+    */
+   if (!strpbrk(exe_cmd, "|&;<>()$`\\\"'*?#"))
+     {
+       char *token;
+       char pre_command = 1;
+       int num_tokens = 0;
+
+       if (!(buf = strdup(exe_cmd)))
+          return;
+
+       token = strtok(buf, " \t\n\v");
+       while (token)
+         {
+            if (token[0] == '~')
+              break;
+            if (pre_command)
+              {
+                 if (token[0] == '[')
+                   break;
+                 if (strchr(token, '='))
+                   break;
+                 else
+                   pre_command = 0;
+              }
+            num_tokens++;
+            token = strtok(NULL, " \t\n\v");
+         }
+       IF_FREE(buf);
+       if ((!token) && (num_tokens))
+         {
+            int i = 0;
+
+            if (!(buf = strdup(exe_cmd)))
+              return;
+
+            token = strtok(buf, " \t\n\v");
+            use_sh = 0;
+            if (!(args = (char **)calloc(num_tokens + 1, sizeof(char *))))
+              {
+                 IF_FREE(buf);
+                 return;
+              }
+            for (i = 0; i < num_tokens; i++)
+              {
+                 if (token)
+                   args[i] = token;
+                 token = strtok(NULL, " \t\n\v");
+              }
+            args[num_tokens] = NULL;
+         }
+     }
+
+   if (!(flags & ECORE_EXE_NOT_LEADER)) setsid();
+   if ((flags & ECORE_EXE_USE_SH))
+     {
+       errno = 0;
+       execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL);
+     }
+   else if (use_sh)
+     {                         /* We have to use a shell to run this. */
+       if (shell == NULL)
+         {                     /* Find users preferred shell. */
+            shell = getenv("SHELL");
+            if (shell == 0)
+              shell = "/bin/sh";
+         }
+       errno = 0;
+       execl(shell, shell, "-c", exe_cmd, (char *)NULL);
+     }
+   else
+     {                         /* We can run this directly. */
+       errno = 0;
+       execvp(args[0], args);
+     }
+
+   save_errno = errno;
+   IF_FREE(buf);
+   IF_FREE(args);
+   errno = save_errno;
+   return;
+}
+
+static int
+_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Exe_Flags flags)
+{
+   Ecore_Exe *exe;
+   int child_fd;
+   int event_type;
+
+   exe = data;
+
+   /* Sort out what sort of handler we are. */
+   if (flags & ECORE_EXE_PIPE_READ)
+     {
+       flags = ECORE_EXE_PIPE_READ;
+       event_type = ECORE_EXE_EVENT_DATA;
+       child_fd = exe->child_fd_read;
+     }
+   else
+     {
+       flags = ECORE_EXE_PIPE_ERROR;
+       event_type = ECORE_EXE_EVENT_ERROR;
+       child_fd = exe->child_fd_error;
+     }
+
+   if ((fd_handler)
+       && (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)))
+     {
+       unsigned char *inbuf;
+       int inbuf_num;
+
+       /* Get any left over data from last time. */
+       if (flags & ECORE_EXE_PIPE_READ)
+         {
+            inbuf = exe->read_data_buf;
+            inbuf_num = exe->read_data_size;
+            exe->read_data_buf = NULL;
+            exe->read_data_size = 0;
+         }
+       else
+         {
+            inbuf = exe->error_data_buf;
+            inbuf_num = exe->error_data_size;
+            exe->error_data_buf = NULL;
+            exe->error_data_size = 0;
+         }
+
+       for (;;)
+         {
+            int num, lost_exe;
+            char buf[READBUFSIZ];
+
+            lost_exe = 0;
+            errno = 0;
+            if ((num = read(child_fd, buf, READBUFSIZ)) < 1)
+              /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE
+               * (currently 64k) to inbuf, use that instead of buf, and
+               * save ourselves a memcpy(). */
+              {
+                 lost_exe = ((errno == EIO) ||
+                             (errno == EBADF) ||
+                             (errno == EPIPE) ||
+                             (errno == EINVAL) || (errno == ENOSPC));
+                 if ((errno != EAGAIN) && (errno != EINTR))
+                    perror("_ecore_exe_generic_handler() read problem ");
+              }
+            if (num > 0)
+              {                /* data got read. */
+                 inbuf = realloc(inbuf, inbuf_num + num);
+                 memcpy(inbuf + inbuf_num, buf, num);
+                 inbuf_num += num;
+              }
+            else
+              {                /* No more data to read. */
+                 if (inbuf)
+                   {
+                      Ecore_Exe_Event_Data *e;
+
+                      /* Stash the data away for later. */
+                      if (flags & ECORE_EXE_PIPE_READ)
+                        {
+                           exe->read_data_buf = inbuf;
+                           exe->read_data_size = inbuf_num;
+                        }
+                      else
+                        {
+                           exe->error_data_buf = inbuf;
+                           exe->error_data_size = inbuf_num;
+                        }
+
+                      if (!(exe->flags & ECORE_EXE_PIPE_AUTO))
+                        {
+                           e = ecore_exe_event_data_get(exe, flags);
+                           if (e)      /* Send the event. */
+                              ecore_event_add(event_type, e,
+                                              _ecore_exe_event_exe_data_free,
+                                              NULL);
+                        }
+                   }
+                 if (lost_exe)
+                   {
+                      if (flags & ECORE_EXE_PIPE_READ)
+                        {
+                           if (exe->read_data_size)
+                              INF("There are %d bytes left unsent from the dead exe %s.",
+                                  exe->read_data_size, exe->cmd);
+                        }
+                      else
+                        {
+                           if (exe->error_data_size)
+                              INF("There are %d bytes left unsent from the dead exe %s.",
+                                  exe->error_data_size, exe->cmd);
+                        }
+                      /* Thought about this a bit.  If the exe has actually
+                       * died, this won't do any harm as it must have died
+                       * recently and the pid has not had a chance to recycle.
+                       * It is also a paranoid catchall, coz the usual ecore_signal
+                       * mechenism should kick in.  But let's give it a good
+                       * kick in the head anyway.
+                       */
+                      ecore_exe_terminate(exe);
+                   }
+                 break;
+              }
+         }
+     }
+
+   return 1;
+}
+
+static int
+_ecore_exe_data_error_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   return _ecore_exe_data_generic_handler(data, fd_handler,
+                                         ECORE_EXE_PIPE_ERROR);
+}
+
+static int
+_ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   return _ecore_exe_data_generic_handler(data, fd_handler,
+                                         ECORE_EXE_PIPE_READ);
+}
+
+static int
+_ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Ecore_Exe *exe;
+
+   exe = data;
+   if ((exe->write_fd_handler) &&
+       (ecore_main_fd_handler_active_get
+       (exe->write_fd_handler, ECORE_FD_WRITE)))
+     _ecore_exe_flush(exe);
+
+   /* If we have sent all there is to send, and we need to close the pipe, then close it. */
+   if ((exe->close_stdin == 1)
+       && (exe->write_data_size == exe->write_data_offset))
+     {
+       int ok = 0;
+       int result;
+
+       INF("Closing stdin for %s", exe->cmd);
+       /* if (exe->child_fd_write != -1)  E_NO_ERRNO(result, fsync(exe->child_fd_write), ok);   This a) doesn't work, and b) isn't needed. */
+       IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
+       if (exe->child_fd_write != -1)
+          E_NO_ERRNO(result, close(exe->child_fd_write), ok);
+       exe->child_fd_write = -1;
+       IF_FREE(exe->write_data_buf);
+     }
+
+   return 1;
+}
+
+static void
+_ecore_exe_flush(Ecore_Exe *exe)
+{
+   int count;
+
+   /* check whether we need to write anything at all. */
+   if ((exe->child_fd_write == -1) || (!exe->write_data_buf))
+      return;
+   if (exe->write_data_size == exe->write_data_offset)
+      return;
+
+   count = write(exe->child_fd_write,
+                (char *)exe->write_data_buf + exe->write_data_offset,
+                exe->write_data_size - exe->write_data_offset);
+   if (count < 1)
+     {
+       if (errno == EIO || errno == EBADF || errno == EPIPE || errno == EINVAL || errno == ENOSPC)     /* we lost our exe! */
+         {
+            ecore_exe_terminate(exe);
+            if (exe->write_fd_handler)
+               ecore_main_fd_handler_active_set(exe->write_fd_handler, 0);
+         }
+     }
+   else
+     {
+       exe->write_data_offset += count;
+       if (exe->write_data_offset >= exe->write_data_size)
+         {                     /* Nothing left to write, clean up. */
+            exe->write_data_size = 0;
+            exe->write_data_offset = 0;
+            IF_FREE(exe->write_data_buf);
+            if (exe->write_fd_handler)
+               ecore_main_fd_handler_active_set(exe->write_fd_handler, 0);
+         }
+     }
+}
+
+static void
+_ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Data *e;
+
+   e = ev;
+   ecore_exe_event_data_free(e);
+}
+
+static Ecore_Exe_Event_Add *
+_ecore_exe_event_add_new(void)
+{
+   Ecore_Exe_Event_Add *e;
+
+   e = calloc(1, sizeof(Ecore_Exe_Event_Add));
+   return e;
+}
+
+static void
+_ecore_exe_event_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Add *e;
+
+   e = ev;
+   free(e);
+}
+
+void               *
+_ecore_exe_event_del_new(void)
+{
+   Ecore_Exe_Event_Del *e;
+
+   e = calloc(1, sizeof(Ecore_Exe_Event_Del));
+   return e;
+}
+
+void
+_ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Del *e;
+
+   e = ev;
+   if (e->exe)
+     ecore_exe_free(e->exe);
+   free(e);
+}
+
+static void
+_ecore_exe_dead_attach(Ecore_Exe *exe)
+{
+   struct _ecore_exe_dead_exe *dead;
+
+   if (exe->doomsday_clock_dead) return;
+   dead = calloc(1, sizeof(struct _ecore_exe_dead_exe));
+   if (dead)
+     {
+       dead->pid = exe->pid;
+       dead->cmd = strdup(exe->cmd);
+       IF_FN_DEL(ecore_timer_del, exe->doomsday_clock);
+       exe->doomsday_clock =
+          ecore_timer_add(10.0, _ecore_exe_make_sure_its_dead, dead);
+       exe->doomsday_clock_dead = dead;
+     }
+}
diff --git a/src/lib/ecore/ecore_exe_win32.c b/src/lib/ecore/ecore_exe_win32.c
new file mode 100644 (file)
index 0000000..b27c57f
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * TODO:
+ * - manage I/O pipes (several ones, and stdin)
+ * - manage SetConsoleCtrlHandler ?
+ * - the child process seems to still run after the DEL event
+ * - add log messages
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <process.h>
+
+#define ECORE_EXE_WIN32_TIMEOUT 3000
+
+typedef enum
+{
+  ECORE_EXE_WIN32_SIGINT,
+  ECORE_EXE_WIN32_SIGQUIT,
+  ECORE_EXE_WIN32_SIGTERM,
+  ECORE_EXE_WIN32_SIGKILL
+} Ecore_Exe_Win32_Signal;
+
+struct _Ecore_Exe
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+
+   HANDLE process2;
+   HANDLE process; /* CloseHandle */
+   HANDLE process_thread;
+   DWORD  process_id;
+   DWORD  thread_id;
+   void  *data;
+   char  *tag;
+   char  *cmd;
+   Ecore_Exe_Flags flags;
+   Ecore_Exe_Win32_Signal sig;
+   Ecore_Win32_Handler *h_close;
+   struct
+   {
+      HANDLE child_pipe;
+      HANDLE child_pipe_x;
+      Ecore_Pipe *p;
+      HANDLE thread;
+      void  *data_buf;
+      int    data_size;
+   } pipe_read;
+   struct
+   {
+      HANDLE child_pipe;
+      HANDLE child_pipe_x;
+      HANDLE thread;
+      Ecore_Win32_Handler *h;
+      void  *data_buf;
+      int    data_size;
+   } pipe_write;
+   struct
+   {
+      HANDLE child_pipe;
+      HANDLE child_pipe_x;
+      Ecore_Pipe *p;
+      HANDLE thread;
+      void  *data_buf;
+      int    data_size;
+   } pipe_error;
+   Eina_Bool    close_stdin : 1;
+   Eina_Bool    is_suspended : 1;
+
+   void (*pre_free_cb)(void *data, const Ecore_Exe *exe);
+};
+
+static Ecore_Exe *exes = NULL;
+
+static int           _ecore_exe_win32_pipes_set(Ecore_Exe *exe);
+static void          _ecore_exe_win32_pipes_close(Ecore_Exe *exe);
+
+static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data);
+static void          _ecore_exe_event_add_free(void *data, void *ev);
+static void          _ecore_exe_event_del_free(void *data, void *ev);
+static void          _ecore_exe_event_exe_data_free(void *data,
+                                                    void *ev);
+static int           _ecore_exe_win32_pipe_thread_generic_cb(void *data, Ecore_Exe_Flags flags);
+static DWORD WINAPI  _ecore_exe_win32_pipe_thread_read_cb(void *data);
+static DWORD WINAPI  _ecore_exe_win32_pipe_thread_error_cb(void *data);
+static int           _ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh);
+static void          _ecore_exe_pipe_read_cb(void *data, void *buf, unsigned int size);
+static int           _ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh);
+static void          _ecore_exe_pipe_error_cb(void *data, void *buf, unsigned int size);
+
+EAPI int ECORE_EXE_EVENT_ADD = 0;
+EAPI int ECORE_EXE_EVENT_DEL = 0;
+EAPI int ECORE_EXE_EVENT_DATA = 0;
+EAPI int ECORE_EXE_EVENT_ERROR = 0;
+
+void
+_ecore_exe_init(void)
+{
+   ECORE_EXE_EVENT_ADD = ecore_event_type_new();
+   ECORE_EXE_EVENT_DEL = ecore_event_type_new();
+   ECORE_EXE_EVENT_DATA = ecore_event_type_new();
+   ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
+}
+
+void
+_ecore_exe_shutdown(void)
+{
+   while (exes)
+      ecore_exe_free(exes);
+}
+
+static int run_pri = NORMAL_PRIORITY_CLASS;
+
+EAPI void
+ecore_exe_run_priority_set(int pri)
+{
+   switch (pri)
+     {
+     case ECORE_EXE_WIN32_PRIORITY_IDLE:
+       run_pri = IDLE_PRIORITY_CLASS;
+       break;
+     case ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL:
+       run_pri = BELOW_NORMAL_PRIORITY_CLASS;
+       break;
+     case ECORE_EXE_WIN32_PRIORITY_NORMAL:
+       run_pri = NORMAL_PRIORITY_CLASS;
+       break;
+     case ECORE_EXE_WIN32_PRIORITY_ABOVE_NORMAL:
+       run_pri = ABOVE_NORMAL_PRIORITY_CLASS;
+       break;
+     case ECORE_EXE_WIN32_PRIORITY_HIGH:
+       run_pri = HIGH_PRIORITY_CLASS;
+       break;
+     case ECORE_EXE_WIN32_PRIORITY_REALTIME:
+       run_pri = REALTIME_PRIORITY_CLASS;
+       break;
+     default:
+       break;
+     }
+}
+
+EAPI int
+ecore_exe_run_priority_get(void)
+{
+   switch (run_pri)
+     {
+     case IDLE_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_IDLE;
+     case BELOW_NORMAL_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL;
+     case NORMAL_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_NORMAL;
+     case ABOVE_NORMAL_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_ABOVE_NORMAL;
+     case HIGH_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_HIGH;
+     case REALTIME_PRIORITY_CLASS:
+       return ECORE_EXE_WIN32_PRIORITY_REALTIME;
+       /* default should not be reached */
+     default:
+       return ECORE_EXE_WIN32_PRIORITY_NORMAL;
+     }
+}
+
+EAPI Ecore_Exe *
+ecore_exe_run(const char *exe_cmd, const void *data)
+{
+   return ecore_exe_pipe_run(exe_cmd, 0, data);
+}
+
+EAPI Ecore_Exe *
+ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
+{
+   STARTUPINFO          si;
+   PROCESS_INFORMATION  pi;
+   Ecore_Exe_Event_Add *e;
+   Ecore_Exe           *exe;
+   char                *ret = NULL;
+
+   exe = calloc(1, sizeof(Ecore_Exe));
+   if (!exe)
+     return NULL;
+
+   if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))
+       && (!(flags & ECORE_EXE_PIPE_READ)))
+     /* We need something to auto pipe. */
+     flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
+
+   exe->flags = flags;
+   if (exe->flags & ECORE_EXE_PIPE_READ)
+     if (!_ecore_exe_win32_pipes_set(exe))
+       goto free_exe;
+  
+   if (exe->flags & ECORE_EXE_PIPE_WRITE)
+     if (!_ecore_exe_win32_pipes_set(exe))
+       goto close_pipes;
+
+   if (exe->flags & ECORE_EXE_PIPE_ERROR)
+     if (!_ecore_exe_win32_pipes_set(exe))
+       goto close_pipes;
+
+   if ((exe->flags & ECORE_EXE_USE_SH) ||
+       ((ret = strrstr(exe_cmd, ".bat")) && (ret[4] == '\0')))
+     {
+        char buf[PATH_MAX];
+        snprintf(buf, PATH_MAX, "cmd.exe /c %s", exe_cmd);
+        exe->cmd = strdup(buf);
+     }
+   else
+     exe->cmd = strdup(exe_cmd);
+
+   if (!exe->cmd)
+     goto close_pipes;
+
+   ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+   ZeroMemory(&si, sizeof(STARTUPINFO));
+   si.cb = sizeof(STARTUPINFO);
+   si.hStdOutput = exe->pipe_read.child_pipe_x;
+   si.hStdInput = exe->pipe_write.child_pipe;
+   si.hStdError = exe->pipe_error.child_pipe_x;
+   si.dwFlags |= STARTF_USESTDHANDLES;
+
+   /* FIXME: gerer la priorite */
+
+   if (!CreateProcess(NULL, exe->cmd, NULL, NULL, EINA_TRUE,
+                      run_pri | CREATE_SUSPENDED, NULL, NULL, &si, &pi))
+     goto free_exe_cmd;
+
+   /* be sure that the child process is running */
+   /* FIXME: This does not work if the child is an EFL-based app */
+   /* if (WaitForInputIdle(pi.hProcess, INFINITE) == WAIT_FAILED) */
+   /*   goto free_exe_cmd; */
+
+   ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
+   exe->process = pi.hProcess;
+   exe->process_thread = pi.hThread;
+   exe->process_id = pi.dwProcessId;
+   exe->thread_id = pi.dwThreadId;
+   exe->data = (void *)data;
+
+   if (!(exe->process2 = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | SYNCHRONIZE,
+                                     EINA_FALSE, pi.dwProcessId)))
+     goto close_thread;
+
+   exe->h_close = ecore_main_win32_handler_add(exe->process2, _ecore_exe_close_cb, exe);
+   if (!exe->h_close) goto close_process2;
+
+   if (ResumeThread(exe->process_thread) == ((DWORD)-1))
+     goto close_process2;
+
+   exes = (Ecore_Exe *)eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+
+   e = (Ecore_Exe_Event_Add *)calloc(1, sizeof(Ecore_Exe_Event_Add));
+   if (!e) goto delete_h_close;
+
+   e->exe = exe;
+   ecore_event_add(ECORE_EXE_EVENT_ADD, e,
+                   _ecore_exe_event_add_free, NULL);
+
+   return exe;
+
+ delete_h_close:
+   ecore_main_win32_handler_del(exe->h_close);
+ close_process2:
+   CloseHandle(exe->process2);
+ close_thread:
+   CloseHandle(exe->process_thread);
+   CloseHandle(exe->process);
+ free_exe_cmd:
+   free(exe->cmd);
+ close_pipes:
+   _ecore_exe_win32_pipes_close(exe);
+ free_exe:
+   free(exe);
+   return NULL;
+}
+
+EAPI void
+ecore_exe_callback_pre_free_set(Ecore_Exe *exe, void (*func)(void *data, const Ecore_Exe *exe))
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
+                         "ecore_exe_callback_pre_free_set");
+        return;
+     }
+   exe->pre_free_cb = func;
+}
+
+EAPI Eina_Bool
+ecore_exe_send(Ecore_Exe *exe, const void *data, int size)
+{
+   void *buf;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_send");
+        return 0;
+     }
+
+   if (exe->close_stdin)
+     {
+        ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
+            exe, size, data);
+        return 0;
+     }
+
+   if (!exe->pipe_write.child_pipe)
+     {
+        ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! "
+            "Cannot send %d bytes from %p", exe, size, data);
+        return 0;
+     }
+
+   buf = realloc(exe->pipe_write.data_buf, exe->pipe_write.data_size + size);
+   if (buf == NULL) return 0;
+
+   exe->pipe_write.data_buf = buf;
+   memcpy((char *)exe->pipe_write.data_buf + exe->pipe_write.data_size, data, size);
+   exe->pipe_write.data_size += size;
+
+   /* if (exe->pipe_write.) */
+   /*    ecore_main_fd_handler_active_set(exe->pipe_write.h, ECORE_FD_WRITE); */
+
+   return 1;
+}
+
+EAPI void
+ecore_exe_close_stdin(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_close_stdin");
+        return;
+     }
+   exe->close_stdin = 1;
+}
+
+/* Not used on Windows */
+EAPI void
+ecore_exe_auto_limits_set(Ecore_Exe *exe __UNUSED__, int start_bytes __UNUSED__, int end_bytes __UNUSED__, int start_lines __UNUSED__, int end_lines __UNUSED__)
+{
+}
+
+EAPI Ecore_Exe_Event_Data *
+ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
+{
+   Ecore_Exe_Event_Data *e = NULL;
+   unsigned char        *inbuf;
+   int                   inbuf_num;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_event_data_get");
+        return NULL;
+     }
+
+   /* Sort out what sort of event we are, */
+   /* And get the data. */
+   if (flags & ECORE_EXE_PIPE_READ)
+     {
+        inbuf = exe->pipe_read.data_buf;
+        inbuf_num = exe->pipe_read.data_size;
+        exe->pipe_read.data_buf = NULL;
+        exe->pipe_read.data_size = 0;
+     }
+   else
+     {
+        inbuf = exe->pipe_error.data_buf;
+        inbuf_num = exe->pipe_error.data_size;
+        exe->pipe_error.data_buf = NULL;
+        exe->pipe_error.data_size = 0;
+     }
+
+   e = calloc(1, sizeof(Ecore_Exe_Event_Data));
+   if (e)
+     {
+        e->exe = exe;
+        e->data = inbuf;
+        e->size = inbuf_num;
+     }
+
+   return e;
+}
+
+EAPI void
+ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
+{
+   if (!e) return;
+   IF_FREE(e->lines);
+   IF_FREE(e->data);
+   free(e);
+}
+
+EAPI void *
+ecore_exe_free(Ecore_Exe *exe)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
+        return NULL;
+     }
+
+   data = exe->data;
+
+   if (exe->pre_free_cb)
+     exe->pre_free_cb(data, exe);
+
+   CloseHandle(exe->process2);
+   CloseHandle(exe->process_thread);
+   CloseHandle(exe->process);
+   free(exe->cmd);
+   _ecore_exe_win32_pipes_close(exe);
+   exes = (Ecore_Exe *)eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+   ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
+   if (exe->tag) free(exe->tag);
+   free(exe);
+
+   return data;
+}
+
+EAPI pid_t
+ecore_exe_pid_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get");
+        return -1;
+     }
+   return exe->process_id;
+}
+
+EAPI void
+ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set");
+        return;
+     }
+   IF_FREE(exe->tag);
+   if (tag)
+      exe->tag = strdup(tag);
+}
+
+EAPI const char *
+ecore_exe_tag_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get");
+        return NULL;
+     }
+   return exe->tag;
+}
+
+EAPI const char *
+ecore_exe_cmd_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get");
+        return NULL;
+     }
+   return exe->cmd;
+}
+
+EAPI void *
+ecore_exe_data_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
+        return NULL;
+     }
+   return exe->data;
+}
+
+EAPI Ecore_Exe_Flags
+ecore_exe_flags_get(const Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
+        return 0;
+     }
+   return exe->flags;
+}
+
+EAPI void
+ecore_exe_pause(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
+        return;
+     }
+
+   if (exe->is_suspended)
+     return;
+
+   if (SuspendThread(exe->process_thread) != (DWORD)-1)
+     exe->is_suspended = 1;
+}
+
+EAPI void
+ecore_exe_continue(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue");
+        return;
+     }
+
+   if (!exe->is_suspended)
+     return;
+
+   if (ResumeThread(exe->process_thread) != (DWORD)-1)
+     exe->is_suspended = 0;
+}
+
+EAPI void
+ecore_exe_interrupt(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt");
+        return;
+     }
+
+   CloseHandle(exe->process_thread);
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGINT;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void
+ecore_exe_quit(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
+        return;
+     }
+
+   CloseHandle(exe->process_thread);
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGQUIT;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void
+ecore_exe_terminate(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate");
+        return;
+     }
+
+/*    CloseHandle(exe->thread); */
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGTERM;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void
+ecore_exe_kill(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
+        return;
+     }
+
+   CloseHandle(exe->process_thread);
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGKILL;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void
+ecore_exe_signal(Ecore_Exe *exe, int num __UNUSED__)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
+        return;
+     }
+
+   /* does nothing */
+}
+
+EAPI void
+ecore_exe_hup(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+        ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
+        return;
+     }
+
+   /* does nothing */
+}
+
+/* FIXME: manage error mode */
+static int
+_ecore_exe_win32_pipe_thread_generic_cb(void *data, Ecore_Exe_Flags flags)
+{
+#define BUFSIZE 2
+   char        buf[BUFSIZE];
+   Ecore_Exe  *exe;
+   char       *current_buf = NULL;
+   HANDLE      child_pipe;
+   Ecore_Pipe *ecore_pipe;
+   Ecore_Exe_Event_Data *event;
+   DWORD       size;
+   DWORD       current_size = 0;
+   BOOL res;
+
+   exe = (Ecore_Exe *)data;
+
+   /* Sort out what sort of handler we are. */
+   /* And get any left over data from last time. */
+   if ((exe->flags & ECORE_EXE_PIPE_READ) && (flags == ECORE_EXE_PIPE_READ))
+     {
+        child_pipe = exe->pipe_read.child_pipe;
+        ecore_pipe = exe->pipe_read.p;
+        flags = ECORE_EXE_PIPE_READ;
+     }
+   else if ((exe->flags & ECORE_EXE_PIPE_ERROR) && (flags == ECORE_EXE_PIPE_ERROR))
+     {
+        child_pipe = exe->pipe_error.child_pipe;
+        ecore_pipe = exe->pipe_error.p;
+        flags = ECORE_EXE_PIPE_ERROR;
+     }
+   else
+     return 0;
+
+   while (1)
+     {
+        if (!PeekNamedPipe(child_pipe, buf, 1, &size, &current_size, NULL))
+          continue;
+        if (size == 0)
+          continue;
+        current_buf = (char *)malloc(current_size);
+        if (!current_buf)
+          continue;
+        res = ReadFile(child_pipe, current_buf, current_size, &size, NULL);
+        if (!res || (size == 0))
+          {
+             free(current_buf);
+             current_buf = NULL;
+             continue;
+          }
+        if (current_size != size)
+          {
+             free(current_buf);
+             current_buf = NULL;
+             continue;
+          }
+        current_size = size;
+
+        if (flags == ECORE_EXE_PIPE_READ)
+          {
+             exe->pipe_read.data_buf = current_buf;
+             exe->pipe_read.data_size = current_size;
+          }
+        else
+          {
+             exe->pipe_error.data_buf = current_buf;
+             exe->pipe_error.data_size = current_size;
+          }
+             
+        event = ecore_exe_event_data_get(exe, flags);
+        if (event)
+          ecore_pipe_write(ecore_pipe, &event, sizeof(event));
+
+        current_buf = NULL;
+        current_size = 0;
+     }
+
+   return 1;
+}
+
+static DWORD WINAPI
+_ecore_exe_win32_pipe_thread_read_cb(void *data)
+{
+  return _ecore_exe_win32_pipe_thread_generic_cb(data, ECORE_EXE_PIPE_READ);
+}
+
+static DWORD WINAPI
+_ecore_exe_win32_pipe_thread_error_cb(void *data)
+{
+  return _ecore_exe_win32_pipe_thread_generic_cb(data, ECORE_EXE_PIPE_ERROR);
+}
+
+static int
+_ecore_exe_win32_pipes_set(Ecore_Exe *exe)
+{
+   SECURITY_ATTRIBUTES sa;
+   HANDLE child_pipe;
+   HANDLE child_pipe_x;
+
+   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+   sa.bInheritHandle = EINA_TRUE;
+   sa.lpSecurityDescriptor = NULL;
+
+   if (!CreatePipe(&child_pipe, &child_pipe_x, &sa, 0))
+     return 0;
+   if (exe->flags & ECORE_EXE_PIPE_WRITE)
+     {
+        if (!SetHandleInformation(child_pipe_x, HANDLE_FLAG_INHERIT, 0))
+          goto close_pipe;
+     }
+   else
+     {
+        if (!SetHandleInformation(child_pipe, HANDLE_FLAG_INHERIT, 0))
+          goto close_pipe;
+     }
+
+   if (exe->flags & ECORE_EXE_PIPE_READ)
+     {
+        exe->pipe_read.child_pipe = child_pipe;
+        exe->pipe_read.child_pipe_x = child_pipe_x;
+        exe->pipe_read.p = ecore_pipe_add(_ecore_exe_pipe_read_cb, exe);
+        exe->pipe_read.thread = CreateThread(NULL, 0,
+                                             _ecore_exe_win32_pipe_thread_read_cb,
+                                             exe, 0, NULL);
+     }
+   else if (exe->flags & ECORE_EXE_PIPE_WRITE)
+     {
+        exe->pipe_write.child_pipe = child_pipe;
+        exe->pipe_write.child_pipe_x = child_pipe_x;
+/*         exe->pipe_write.thread = CreateThread(NULL, 0, */
+/*                                              _ecore_exe_win32_pipe_thread_cb, */
+/*                                              exe, 0, NULL); */
+     }
+   else
+     {
+        exe->pipe_error.child_pipe = child_pipe;
+        exe->pipe_error.child_pipe_x = child_pipe_x;
+        exe->pipe_error.p = ecore_pipe_add(_ecore_exe_pipe_error_cb, exe);
+        exe->pipe_error.thread = CreateThread(NULL, 0,
+                                             _ecore_exe_win32_pipe_thread_error_cb,
+                                             exe, 0, NULL);
+     }
+
+   return 1;
+
+ close_pipe:
+   CloseHandle(child_pipe);
+   CloseHandle(child_pipe_x);
+
+   return 0;
+}
+
+static void
+_ecore_exe_win32_pipes_close(Ecore_Exe *exe)
+{
+   if (exe->flags & ECORE_EXE_PIPE_READ)
+     {
+       if (exe->pipe_read.child_pipe)
+         {
+            CloseHandle(exe->pipe_read.child_pipe);
+            exe->pipe_read.child_pipe = NULL;
+         }
+       if (exe->pipe_read.child_pipe_x)
+         {
+           CloseHandle(exe->pipe_read.child_pipe_x);
+           exe->pipe_read.child_pipe_x = NULL;
+         }
+     }
+
+   if (exe->flags & ECORE_EXE_PIPE_WRITE)
+     {
+       if (exe->pipe_write.child_pipe)
+         {
+            CloseHandle(exe->pipe_write.child_pipe);
+            exe->pipe_write.child_pipe = NULL;
+         }
+       if (exe->pipe_write.child_pipe_x)
+         {
+           CloseHandle(exe->pipe_write.child_pipe_x);
+           exe->pipe_write.child_pipe_x = NULL;
+         }
+     }
+
+   if (exe->flags & ECORE_EXE_PIPE_ERROR)
+     {
+       if (exe->pipe_error.child_pipe)
+         {
+            CloseHandle(exe->pipe_error.child_pipe);
+            exe->pipe_error.child_pipe = NULL;
+         }
+       if (exe->pipe_error.child_pipe_x)
+         {
+           CloseHandle(exe->pipe_error.child_pipe_x);
+           exe->pipe_error.child_pipe_x = NULL;
+         }
+     }
+}
+
+static DWORD WINAPI
+_ecore_exe_thread_procedure(LPVOID data __UNUSED__)
+{
+   GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+   GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
+   return 1;
+}
+
+static BOOL CALLBACK
+_ecore_exe_enum_windows_procedure(HWND window, LPARAM data)
+{
+   Ecore_Exe *exe;
+   DWORD      thread_id;
+
+   exe = (Ecore_Exe *)data;
+   thread_id = GetWindowThreadProcessId(window, NULL);
+
+   if (thread_id == exe->thread_id)
+     {
+        /* Ctrl-C or Ctrl-Break */
+        if (CreateRemoteThread(exe->process, NULL, 0,
+                               (LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL,
+                               0, NULL))
+          {
+            printf ("remote thread\n");
+            return EINA_FALSE;
+          }
+
+        if ((exe->sig == ECORE_EXE_WIN32_SIGINT) ||
+            (exe->sig == ECORE_EXE_WIN32_SIGQUIT))
+          {
+            printf ("int or quit\n");
+            return EINA_FALSE;
+          }
+
+        /* WM_CLOSE message */
+        PostMessage(window, WM_CLOSE, 0, 0);
+        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
+          {
+            printf ("CLOSE\n");
+            return EINA_FALSE;
+          }
+
+        /* WM_QUIT message */
+        PostMessage(window, WM_QUIT, 0, 0);
+        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
+          {
+            printf ("QUIT\n");
+            return EINA_FALSE;
+          }
+
+        /* Exit process */
+        if (CreateRemoteThread(exe->process, NULL, 0,
+                               (LPTHREAD_START_ROUTINE)ExitProcess, NULL,
+                               0, NULL))
+          {
+            printf ("remote thread 2\n");
+            return EINA_FALSE;
+          }
+
+        if (exe->sig == ECORE_EXE_WIN32_SIGTERM)
+          {
+            printf ("term\n");
+            return EINA_FALSE;
+          }
+
+        TerminateProcess(exe->process, 0);
+
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_ecore_exe_event_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Add *e;
+
+   e = (Ecore_Exe_Event_Add *)ev;
+   free(e);
+}
+
+static void
+_ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Del *e;
+
+   e = (Ecore_Exe_Event_Del *)ev;
+   if (e->exe)
+     ecore_exe_free(e->exe);
+   free(e);
+}
+
+static void
+_ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Exe_Event_Data *e;
+
+   e = (Ecore_Exe_Event_Data *)ev;
+   ecore_exe_event_data_free(e);
+}
+
+static int
+_ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
+{
+   Ecore_Exe_Event_Del *e;
+   Ecore_Exe           *exe;
+   DWORD                exit_code = 0;
+
+   e = calloc(1, sizeof(Ecore_Exe_Event_Del));
+   if (!e) return 0;
+
+   exe = (Ecore_Exe *)data;
+
+   if (GetExitCodeProcess(exe->process2, &exit_code))
+     {
+        e->exit_code = exit_code;
+        e->exited = 1;
+     }
+   else
+     {
+        char *msg;
+
+        msg = evil_last_error_get();
+        printf("%s\n", msg);
+        free(msg);
+     }
+     e->pid = exe->process_id;
+     e->exe = exe;
+
+     ecore_event_add(ECORE_EXE_EVENT_DEL, e,
+                     _ecore_exe_event_del_free, NULL);
+     
+   return 0;
+}
+
+static void
+_ecore_exe_pipe_read_cb(void *data, void *buf, unsigned int size)
+{
+   Ecore_Exe_Event_Data *e;
+
+   e = *((Ecore_Exe_Event_Data **)buf);
+   if (e)
+     ecore_event_add(ECORE_EXE_EVENT_DATA, e,
+                     _ecore_exe_event_exe_data_free,
+                     NULL);
+}
+
+static int
+_ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
+{
+   char       buf[READBUFSIZ];
+   Ecore_Exe *exe;
+   DWORD      num_exe;
+   BOOL       res;
+
+   exe = (Ecore_Exe *)data;
+
+   res = WriteFile(exe->pipe_write.child_pipe_x, buf, READBUFSIZ, &num_exe, NULL);
+   if (!res || num_exe == 0)
+     {
+       /* FIXME: what to do here ?? */
+     }
+
+   if (exe->close_stdin == 1)
+     {
+        if (exe->pipe_write.h)
+          {
+             ecore_main_win32_handler_del(exe->pipe_write.h);
+             exe->pipe_write.h = NULL;
+          }
+        exe->pipe_write.h = NULL;
+        CloseHandle(exe->pipe_write.child_pipe);
+        exe->pipe_write.child_pipe = NULL;
+     }
+
+   return 1;
+}
+
+static void
+_ecore_exe_pipe_error_cb(void *data, void *buf, unsigned int size)
+{
+   Ecore_Exe_Event_Data *e;
+
+   e = *((Ecore_Exe_Event_Data **)buf);
+   if (e)
+     ecore_event_add(ECORE_EXE_EVENT_ERROR, e,
+                     _ecore_exe_event_exe_data_free,
+                     NULL);
+}
diff --git a/src/lib/ecore/ecore_exe_wince.c b/src/lib/ecore/ecore_exe_wince.c
new file mode 100644 (file)
index 0000000..2b2e60a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+void
+_ecore_exe_init(void)
+{
+}
+
+void
+_ecore_exe_shutdown(void)
+{
+}
diff --git a/src/lib/ecore/ecore_getopt.c b/src/lib/ecore/ecore_getopt.c
new file mode 100644 (file)
index 0000000..af18922
--- /dev/null
@@ -0,0 +1,1739 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# include <stddef.h>
+# ifdef  __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+#else
+# define gettext(x) (x)
+# define dgettext(domain, x) (x)
+#endif
+
+#define _(x) dgettext("ecore", x)
+
+#ifdef _WIN32_WCE
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "Ecore_Getopt.h"
+
+static const char *prog = NULL;
+static char **argv = NULL;
+static int argc = 0;
+static int cols = 80;
+static int helpcol = 80 / 3;
+
+static void
+_ecore_getopt_help_print_replace_program(FILE *fp, const Ecore_Getopt *parser __UNUSED__, const char *text)
+{
+   do
+     {
+       const char *d = strchr(text, '%');
+
+       if (!d)
+         {
+            fputs(text, fp);
+            break;
+         }
+
+       if (fwrite(text, 1, d - text, fp) != (size_t)(d - text))
+         return;
+       d++;
+       if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
+         {
+            fputs(prog ? prog : "???", fp);
+            d += sizeof("prog") - 1;
+         }
+       else
+         {
+            if (d[0] == '%')
+              d++;
+            fputc('%', fp);
+         }
+
+       text = d;
+     }
+   while (text[0] != '\0');
+
+   fputc('\n', fp);
+}
+
+static void
+_ecore_getopt_version(FILE *fp, const Ecore_Getopt *parser)
+{
+   fputs(_("Version:"), fp);
+   fputc(' ', fp);
+   _ecore_getopt_help_print_replace_program(fp, parser, parser->version);
+}
+
+static void
+_ecore_getopt_help_usage(FILE *fp, const Ecore_Getopt *parser)
+{
+   fputs(_("Usage:"), fp);
+   fputc(' ', fp);
+
+   if (!parser->usage)
+     {
+       fprintf(fp, _("%s [options]\n"), prog);
+       return;
+     }
+
+   _ecore_getopt_help_print_replace_program(fp, parser, gettext(parser->usage));
+}
+
+static int
+_ecore_getopt_help_line(FILE *fp, const int base, const int total, int used, const char *text, int len)
+{
+   int linebreak = 0;
+   do
+     {
+       /* process line considering spaces (new line and tabs are spaces!) */
+       while ((used < total) && (len > 0))
+         {
+            const char *space = NULL;
+            int i, todo;
+
+            todo = total - used;
+            if (todo > len)
+              todo = len;
+
+            for (i = 0; i < todo; i++)
+              if (isspace(text[i]))
+                {
+                   space = text + i;
+                   break;
+                }
+
+            if (space)
+              {
+                 i = fwrite(text, 1, i, fp);
+                 i++;
+                 text += i;
+                 len -= i;
+                 used += i;
+
+                 if (linebreak)
+                   {
+                      linebreak = 0;
+                      continue;
+                   }
+
+                 if (space[0] == '\n')
+                   break;
+                 else if (space[0] == '\t')
+                   {
+                      int c;
+
+                      used--;
+                      c = ((used / 8) + 1) * 8;
+                      if (c < total)
+                        {
+                           for (; used < c; used++)
+                             fputc(' ', fp);
+                        }
+                      else
+                        {
+                           text--;
+                           len++;
+                           break;
+                        }
+                   }
+                 else if (used < total)
+                   fputc(space[0], fp);
+              }
+            else
+              {
+                 i = fwrite(text, 1, i, fp);
+                 text += i;
+                 len -= i;
+                 used += i;
+              }
+            linebreak = 0;
+         }
+       if (len <= 0)
+         break;
+       linebreak = 1;
+       fputc('\n', fp);
+       for (used = 0; used < base; used++)
+         fputc(' ', fp);
+     }
+   while (1);
+
+   return used;
+}
+
+static void
+_ecore_getopt_help_description(FILE *fp, const Ecore_Getopt *parser)
+{
+   const char *p, *prg, *ver;
+   int used, prglen, verlen;
+
+   p = gettext(parser->description);
+   if (!p)
+     return;
+
+   fputc('\n', fp);
+
+   prg = prog ? prog : "???";
+   ver = parser->version ? parser->version : "???";
+
+   prglen = strlen(prg);
+   verlen = strlen(ver);
+
+   used = 0;
+
+   do
+     {
+       const char *d = strchr(p, '%');
+
+       if (!d)
+         {
+            _ecore_getopt_help_line(fp, 0, cols, used, p, strlen(p));
+            break;
+         }
+
+       used = _ecore_getopt_help_line(fp, 0, cols, used, p, d - p);
+       d++;
+       if (strncmp(d, "prog", sizeof("prog") - 1) == 0)
+         {
+            used = _ecore_getopt_help_line(fp, 0, cols, used, prg, prglen);
+            d += sizeof("prog") - 1;
+         }
+       else if (strncmp(d, "version", sizeof("version") - 1) == 0)
+         {
+            used = _ecore_getopt_help_line(fp, 0, cols, used, ver, verlen);
+            d += sizeof("version") - 1;
+         }
+       else
+         {
+            if (d[0] == '%')
+              d++;
+            used = _ecore_getopt_help_line(fp, 0, cols, used, "%", 1);
+         }
+
+       p = d;
+     }
+   while (p[0] != '\0');
+
+   fputs("\n\n", fp);
+}
+
+static void
+_ecore_getopt_copyright(FILE *fp, const Ecore_Getopt *parser)
+{
+   const char *txt = gettext(parser->copyright);
+   fputs(_("Copyright:"), fp);
+   fputs("\n   ", fp);
+   _ecore_getopt_help_line
+     (fp, 3, cols, 3, txt, strlen(txt));
+   fputc('\n', fp);
+}
+
+static void
+_ecore_getopt_license(FILE *fp, const Ecore_Getopt *parser)
+{
+   const char *txt = gettext(parser->license);
+   fputs(_("License:"), fp);
+   fputs("\n   ", fp);
+   _ecore_getopt_help_line
+     (fp, 3, cols, 3, txt, strlen(txt));
+   fputc('\n', fp);
+}
+
+static Ecore_Getopt_Desc_Arg_Requirement
+_ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
+{
+   switch (desc->action)
+     {
+      case ECORE_GETOPT_ACTION_STORE:
+        return desc->action_param.store.arg_req;
+      case ECORE_GETOPT_ACTION_STORE_CONST:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      case ECORE_GETOPT_ACTION_STORE_TRUE:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      case ECORE_GETOPT_ACTION_STORE_FALSE:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      case ECORE_GETOPT_ACTION_CHOICE:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
+      case ECORE_GETOPT_ACTION_APPEND:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES;
+      case ECORE_GETOPT_ACTION_COUNT:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      case ECORE_GETOPT_ACTION_CALLBACK:
+        return desc->action_param.callback.arg_req;
+      case ECORE_GETOPT_ACTION_HELP:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      case ECORE_GETOPT_ACTION_VERSION:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+      default:
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+     }
+}
+
+static void
+_ecore_getopt_help_desc_setup_metavar(const Ecore_Getopt_Desc *desc, char *metavar, int *metavarlen, int maxsize)
+{
+   if (desc->metavar)
+     {
+       const char *txt = gettext(desc->metavar);
+       *metavarlen = strlen(txt);
+       if (*metavarlen > maxsize - 1)
+         *metavarlen = maxsize - 1;
+
+       memcpy(metavar, txt, *metavarlen);
+       metavar[*metavarlen] = '\0';
+     }
+   else if (desc->longname)
+     {
+       int i;
+
+       *metavarlen = strlen(desc->longname);
+       if (*metavarlen > maxsize - 1)
+         *metavarlen = maxsize - 1;
+
+       for (i = 0; i < *metavarlen; i++)
+         metavar[i] = toupper(desc->longname[i]);
+       metavar[i] = '\0';
+     }
+}
+
+static int
+_ecore_getopt_help_desc_show_arg(FILE *fp, Ecore_Getopt_Desc_Arg_Requirement requirement, const char *metavar, int metavarlen)
+{
+   int used;
+
+   if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+     return 0;
+
+   used = 0;
+
+   if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
+     {
+       fputc('[', fp);
+       used++;
+     }
+
+   if (requirement != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+     {
+       fputc('=', fp);
+       fputs(metavar, fp);
+       used += metavarlen + 1;
+     }
+
+   if (requirement == ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL)
+     {
+       fputc(']', fp);
+       used++;
+     }
+
+   return used;
+}
+
+static int
+_ecore_getopt_help_desc_store(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
+{
+   const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
+   char buf[64];
+   const char *str;
+   size_t len;
+
+   fputc('\n', fp);
+   for (used = 0; used < base; used++)
+     fputc(' ', fp);
+
+   switch (store->type)
+     {
+      case ECORE_GETOPT_TYPE_STR:
+        str = "STR";
+        len = sizeof("STR") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_BOOL:
+        str = "BOOL";
+        len = sizeof("BOOL") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_SHORT:
+        str = "SHORT";
+        len = sizeof("SHORT") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_INT:
+        str = "INT";
+        len = sizeof("INT") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_LONG:
+        str = "LONG";
+        len = sizeof("LONG") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_USHORT:
+        str = "USHORT";
+        len = sizeof("USHORT") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_UINT:
+        str = "UINT";
+        len = sizeof("UINT") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_ULONG:
+        str = "ULONG";
+        len = sizeof("ULONG") - 1;
+        break;
+      case ECORE_GETOPT_TYPE_DOUBLE:
+        str = "DOUBLE";
+        len = sizeof("DOUBLE") - 1;
+        break;
+      default:
+        str = "???";
+        len = sizeof("???") - 1;
+     }
+
+   used = _ecore_getopt_help_line
+     (fp, base, total, used, _("Type: "), strlen(_("Type: ")));
+   used = _ecore_getopt_help_line(fp, base, total, used, str, len);
+
+   if (store->arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES)
+     goto end;
+
+   used = _ecore_getopt_help_line
+     (fp, base, total, used, ". ", sizeof(". ") - 1);
+
+   switch (store->type)
+     {
+      case ECORE_GETOPT_TYPE_STR:
+        str = store->def.strv;
+        len = str ? strlen(str) : 0;
+        break;
+      case ECORE_GETOPT_TYPE_BOOL:
+        str = store->def.boolv ? "true" : "false";
+        len = strlen(str);
+        break;
+      case ECORE_GETOPT_TYPE_SHORT:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%hd", store->def.shortv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_INT:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%d", store->def.intv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_LONG:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%ld", store->def.longv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_USHORT:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%hu", store->def.ushortv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_UINT:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%u", store->def.uintv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_ULONG:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%lu", store->def.ulongv);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      case ECORE_GETOPT_TYPE_DOUBLE:
+        str = buf;
+        len = snprintf(buf, sizeof(buf), "%f", store->def.doublev);
+        if (len > sizeof(buf) - 1)
+          len = sizeof(buf) - 1;
+        break;
+      default:
+        str = "???";
+        len = sizeof("???") - 1;
+     }
+
+   used = _ecore_getopt_help_line
+     (fp, base, total, used, _("Default: "), strlen(_("Default: ")));
+   used = _ecore_getopt_help_line(fp, base, total, used, str, len);
+
+ end:
+   return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
+}
+
+static int
+_ecore_getopt_help_desc_choices(FILE *fp, const int base, const int total, int used, const Ecore_Getopt_Desc *desc)
+{
+   const char *const *itr;
+   const char sep[] = ", ";
+   const int seplen = sizeof(sep) - 1;
+
+   if (used > 0)
+     {
+       fputc('\n', fp);
+       used = 0;
+     }
+   for (; used < base; used++)
+     fputc(' ', fp);
+
+   used = _ecore_getopt_help_line
+     (fp, base, total, used, _("Choices: "), strlen(_("Choices: ")));
+
+   for (itr = desc->action_param.choices; *itr != NULL; itr++)
+     {
+       used = _ecore_getopt_help_line
+         (fp, base, total, used, *itr, strlen(*itr));
+       if (itr[1] != NULL)
+         used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
+     }
+
+   return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
+}
+
+static void
+_ecore_getopt_help_desc(FILE *fp, const Ecore_Getopt_Desc *desc)
+{
+   Ecore_Getopt_Desc_Arg_Requirement arg_req;
+   char metavar[32] = "ARG";
+   int metavarlen = 3;
+   int used;
+
+   arg_req = _ecore_getopt_desc_arg_requirement(desc);
+   if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+     _ecore_getopt_help_desc_setup_metavar
+       (desc, metavar, &metavarlen, sizeof(metavar));
+
+   fputs("  ", fp);
+   used = 2;
+
+   if (desc->shortname)
+     {
+       fputc('-', fp);
+       fputc(desc->shortname, fp);
+       used += 2;
+       used += _ecore_getopt_help_desc_show_arg
+         (fp, arg_req, metavar, metavarlen);
+     }
+
+   if (desc->shortname && desc->longname)
+     {
+       fputs(", ", fp);
+       used += 2;
+     }
+
+   if (desc->longname)
+     {
+       int namelen = strlen(desc->longname);
+
+       fputs("--", fp);
+       fputs(desc->longname, fp);
+       used += 2 + namelen;
+       used += _ecore_getopt_help_desc_show_arg
+         (fp, arg_req, metavar, metavarlen);
+     }
+
+   if (!desc->help)
+     goto end;
+
+   if (used + 3 >= helpcol)
+     {
+       fputc('\n', fp);
+       used = 0;
+     }
+
+   for (; used < helpcol; used++)
+     fputc(' ', fp);
+
+   used = _ecore_getopt_help_line
+     (fp, helpcol, cols, used, desc->help, strlen(desc->help));
+
+   switch (desc->action)
+     {
+      case ECORE_GETOPT_ACTION_STORE:
+        _ecore_getopt_help_desc_store(fp, helpcol, cols, used, desc);
+        break;
+      case ECORE_GETOPT_ACTION_CHOICE:
+        _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
+        break;
+      default:
+        break;
+     }
+
+ end:
+   fputc('\n', fp);
+}
+
+static unsigned char
+_ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
+{
+   return (desc->shortname == '\0') && (desc->longname == NULL);
+}
+
+static void
+_ecore_getopt_help_options(FILE *fp, const Ecore_Getopt *parser)
+{
+   const Ecore_Getopt_Desc *desc;
+
+   fputs(_("Options:\n"), fp);
+
+   for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     _ecore_getopt_help_desc(fp, desc);
+
+   fputc('\n', fp);
+}
+
+/**
+ * Show nicely formatted help message for the given parser.
+ *
+ * Message will be print to stderr.
+ */
+void
+ecore_getopt_help(FILE *fp, const Ecore_Getopt *parser)
+{
+   const char *var;
+
+   if (!parser) return;
+
+   if (argc < 1)
+     {
+       ecore_app_args_get(&argc, &argv);
+       if ((argc > 0) && (argv[0] != NULL))
+         prog = argv[0];
+       else
+         prog = parser->prog;
+     }
+
+   var = getenv("COLUMNS");
+   if (var)
+     {
+       cols = atoi(var);
+       if (cols < 20)
+         cols = 20;
+
+       helpcol = cols / 3;
+     }
+
+   _ecore_getopt_help_usage(fp, parser);
+   _ecore_getopt_help_description(fp, parser);
+   _ecore_getopt_help_options(fp, parser);
+}
+
+static const Ecore_Getopt_Desc *
+_ecore_getopt_parse_find_long(const Ecore_Getopt *parser, const char *name)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   const char *p = strchr(name, '=');
+   int len = 0;
+
+   if (p)
+     len = p - name;
+
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+       if (!desc->longname)
+         continue;
+
+       if (p)
+         {
+            if ((strncmp(name, desc->longname, len) == 0) &&
+                (desc->longname[len] == '\0'))
+              return desc;
+         }
+       else
+         {
+            if (strcmp(name, desc->longname) == 0)
+              return desc;
+         }
+     }
+
+   return NULL;
+}
+
+static const Ecore_Getopt_Desc *
+_ecore_getopt_parse_find_short(const Ecore_Getopt *parser, char name)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     if (name == desc->shortname)
+       return desc;
+   return NULL;
+}
+
+static int
+_ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser, int argc, char **argv)
+{
+   char **nonargs;
+   int src, dst, used, base;
+
+   nonargs = alloca(sizeof(char*) * argc);
+   src = 1;
+   dst = 1;
+   used = 0;
+   base = 0;
+   while (src < argc)
+     {
+       const Ecore_Getopt_Desc *desc;
+       Ecore_Getopt_Desc_Arg_Requirement arg_req;
+       char *arg = argv[src];
+
+       if (arg[0] != '-')
+         goto found_nonarg;
+
+       if (arg[1] == '-')
+         {
+            if (arg[2] == '\0') /* explicit end of options, "--" */
+              {
+                 base = 1;
+                 break;
+              }
+            desc = _ecore_getopt_parse_find_long(parser, arg + 2);
+         }
+       else
+         desc = _ecore_getopt_parse_find_short(parser, arg[1]);
+
+       if (!desc)
+         {
+            if (arg[1] == '-')
+              fprintf(stderr, _("ERROR: unknown option --%s.\n"), arg + 2);
+            else
+              fprintf(stderr, _("ERROR: unknown option -%c.\n"), arg[1]);
+            if (parser->strict)
+              {
+                 memmove(argv + dst, nonargs, used * sizeof(char *));
+                 return -1;
+              }
+            else
+              goto found_nonarg;
+         }
+
+       if (src != dst)
+         argv[dst] = argv[src];
+       src++;
+       dst++;
+
+       arg_req = _ecore_getopt_desc_arg_requirement(desc);
+       if (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+         continue;
+
+       if (strchr(arg, '='))
+         continue;
+
+       if ((src >= argc) || (argv[src][0] == '-'))
+         continue;
+
+       if (src != dst)
+         argv[dst] = argv[src];
+       src++;
+       dst++;
+       continue;
+
+     found_nonarg:
+       nonargs[used] = arg;
+       used++;
+       src++;
+     }
+
+   if (!base) /* '--' not found */
+     base = dst;
+   else
+     {
+       base = dst;
+       if (src != dst)
+         argv[dst] = argv[src];
+       dst++;
+     }
+
+   memmove(argv + dst, nonargs, used * sizeof(char *));
+   return base;
+}
+
+static void
+_ecore_getopt_desc_print_error(const Ecore_Getopt_Desc *desc, const char *fmt, ...)
+{
+   va_list ap;
+
+   fputs(_("ERROR: "), stderr);
+
+   if (desc->shortname)
+     {
+       fputc('-', stderr);
+       fputc(desc->shortname, stderr);
+     }
+
+   if (desc->shortname && desc->longname)
+     fputs(", ", stderr);
+
+   if (desc->longname)
+     {
+       fputs("--", stderr);
+       fputs(desc->longname, stderr);
+     }
+
+   fputs(": ", stderr);
+
+   va_start(ap, fmt);
+   vfprintf(stderr, fmt, ap);
+   va_end(ap);
+}
+
+static unsigned char
+_ecore_getopt_parse_bool(const char *str, unsigned char *v)
+{
+   if ((strcmp(str, "0") == 0) ||
+       (strcasecmp(str, "f") == 0) ||
+       (strcasecmp(str, "false") == 0) ||
+       (strcasecmp(str, "no") == 0) ||
+       (strcasecmp(str, "off") == 0)
+       )
+     {
+       *v = 0;
+       return 1;
+     }
+   else if ((strcmp(str, "1") == 0) ||
+           (strcasecmp(str, "t") == 0) ||
+           (strcasecmp(str, "true") == 0) ||
+           (strcasecmp(str, "yes") == 0) ||
+           (strcasecmp(str, "on") == 0)
+           )
+     {
+       *v = 1;
+       return 1;
+     }
+
+   return 0;
+}
+
+static unsigned char
+_ecore_getopt_parse_long(const char *str, long int *v)
+{
+   char *endptr = NULL;
+   *v = strtol(str, &endptr, 0);
+   return endptr > str;
+}
+
+static unsigned char
+_ecore_getopt_parse_double(const char *str, double *v)
+{
+   char *endptr = NULL;
+   *v = strtod(str, &endptr);
+   return endptr > str;
+}
+
+static unsigned char
+_ecore_getopt_parse_store(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
+{
+   const Ecore_Getopt_Desc_Store *store = &desc->action_param.store;
+   long int v;
+   double d;
+   unsigned char b;
+
+   if (!value->ptrp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+
+   switch (store->arg_req)
+     {
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
+        goto use_optional;
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
+        if (!arg_val)
+          goto use_optional;
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
+        break;
+     }
+
+   switch (store->type)
+     {
+      case ECORE_GETOPT_TYPE_STR:
+        *value->strp = (char *)arg_val;
+        return 1;
+      case ECORE_GETOPT_TYPE_BOOL:
+        if (_ecore_getopt_parse_bool(arg_val, &b))
+          {
+             *value->boolp = b;
+             return 1;
+          }
+        else
+          {
+             _ecore_getopt_desc_print_error
+               (desc, _("unknown boolean value %s.\n"), arg_val);
+             return 0;
+          }
+      case ECORE_GETOPT_TYPE_SHORT:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->shortp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_INT:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->intp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_LONG:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->longp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_USHORT:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->ushortp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_UINT:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->uintp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_ULONG:
+        if (!_ecore_getopt_parse_long(arg_val, &v))
+          goto error;
+        *value->ulongp = v;
+        return 1;
+      case ECORE_GETOPT_TYPE_DOUBLE:
+        if (!_ecore_getopt_parse_double(arg_val, &d))
+          goto error;
+        *value->doublep = d;
+        break;
+     }
+
+   return 1;
+
+ error:
+   _ecore_getopt_desc_print_error
+     (desc, _("invalid number format %s\n"), arg_val);
+   return 0;
+
+ use_optional:
+   switch (store->type)
+     {
+      case ECORE_GETOPT_TYPE_STR:
+        *value->strp = (char *)store->def.strv;
+        break;
+      case ECORE_GETOPT_TYPE_BOOL:
+        *value->boolp = store->def.boolv;
+        break;
+      case ECORE_GETOPT_TYPE_SHORT:
+        *value->shortp = store->def.shortv;
+        break;
+      case ECORE_GETOPT_TYPE_INT:
+        *value->intp = store->def.intv;
+        break;
+      case ECORE_GETOPT_TYPE_LONG:
+        *value->longp = store->def.longv;
+        break;
+      case ECORE_GETOPT_TYPE_USHORT:
+        *value->ushortp = store->def.ushortv;
+        break;
+      case ECORE_GETOPT_TYPE_UINT:
+        *value->uintp = store->def.uintv;
+        break;
+      case ECORE_GETOPT_TYPE_ULONG:
+        *value->ulongp = store->def.ulongv;
+        break;
+      case ECORE_GETOPT_TYPE_DOUBLE:
+        *value->doublep = store->def.doublev;
+        break;
+     }
+
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_store_const(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (!val->ptrp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+
+   *val->ptrp = (void *)desc->action_param.store_const;
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_store_true(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (!val->boolp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+   *val->boolp = 1;
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_store_false(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (!val->boolp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+   *val->boolp = 0;
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_choice(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
+{
+   const char * const *pchoice;
+
+   if (!val->strp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+
+   pchoice = desc->action_param.choices;
+   for (; *pchoice != NULL; pchoice++)
+     if (strcmp(*pchoice, arg_val) == 0)
+       {
+         *val->strp = (char *)*pchoice;
+         return 1;
+       }
+
+   _ecore_getopt_desc_print_error
+     (desc, _("invalid choice \"%s\". Valid values are: "), arg_val);
+
+   pchoice = desc->action_param.choices;
+   for (; *pchoice != NULL; pchoice++)
+     {
+       fputs(*pchoice, stderr);
+       if (pchoice[1] != NULL)
+         fputs(", ", stderr);
+     }
+
+   fputs(".\n", stderr);
+   return 0;
+}
+
+static unsigned char
+_ecore_getopt_parse_append(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
+{
+   void *data;
+   long int v;
+   double d;
+   unsigned char b;
+
+   if (!arg_val)
+     {
+       _ecore_getopt_desc_print_error
+         (desc, _("missing parameter to append.\n"));
+       return 0;
+     }
+
+   if (!val->listp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+
+   switch (desc->action_param.append_type)
+     {
+      case ECORE_GETOPT_TYPE_STR:
+        data = strdup(arg_val);
+        break;
+      case ECORE_GETOPT_TYPE_BOOL:
+       {
+          if (_ecore_getopt_parse_bool(arg_val, &b))
+            {
+               data = malloc(sizeof(unsigned char));
+               if (data)
+                 *(unsigned char *)data = b;
+            }
+          else
+            {
+               _ecore_getopt_desc_print_error
+                 (desc, _("unknown boolean value %s.\n"), arg_val);
+               return 0;
+            }
+       }
+       break;
+      case ECORE_GETOPT_TYPE_SHORT:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(short));
+          if (data)
+            *(short *)data = (short)v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_INT:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(int));
+          if (data)
+            *(int *)data = (int)v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_LONG:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(long));
+          if (data)
+            *(long *)data = v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_USHORT:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(unsigned short));
+          if (data)
+            *(unsigned short *)data = (unsigned short)v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_UINT:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(unsigned int));
+          if (data)
+            *(unsigned int *)data = (unsigned int)v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_ULONG:
+       {
+          if (!_ecore_getopt_parse_long(arg_val, &v))
+            goto error;
+          data = malloc(sizeof(unsigned long));
+          if (data)
+            *(unsigned long *)data = v;
+       }
+       break;
+      case ECORE_GETOPT_TYPE_DOUBLE:
+       {
+          if (!_ecore_getopt_parse_double(arg_val, &d))
+            goto error;
+          data = malloc(sizeof(double));
+          if (data)
+            *(double *)data = d;
+       }
+       break;
+      default:
+       {
+          _ecore_getopt_desc_print_error(desc, _("could not parse value.\n"));
+          return 0;
+       }
+     }
+
+   *val->listp = eina_list_append(*val->listp, data);
+   return 1;
+
+ error:
+   _ecore_getopt_desc_print_error
+     (desc, _("invalid number format %s\n"), arg_val);
+   return 0;
+}
+
+static unsigned char
+_ecore_getopt_parse_count(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (!val->intp)
+     {
+       _ecore_getopt_desc_print_error(desc, _("value has no pointer set.\n"));
+       return 0;
+     }
+
+   (*val->intp)++;
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_callback(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val)
+{
+   const Ecore_Getopt_Desc_Callback *cb = &desc->action_param.callback;
+
+   switch (cb->arg_req)
+     {
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO:
+        arg_val = cb->def;
+        break;
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL:
+        if (!arg_val)
+          arg_val = cb->def;
+        break;
+      case ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES:
+        break;
+     }
+
+   if (cb->arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+     {
+       if ((!arg_val) || (arg_val[0] == '\0'))
+         {
+            _ecore_getopt_desc_print_error(desc, _("missing parameter.\n"));
+            return 0;
+         }
+
+       if (!val->ptrp)
+         {
+            _ecore_getopt_desc_print_error
+              (desc, _("value has no pointer set.\n"));
+            return 0;
+         }
+     }
+
+   if (!cb->func)
+     {
+       _ecore_getopt_desc_print_error(desc, _("missing callback function!\n"));
+       return 0;
+     }
+
+   return cb->func(parser, desc, arg_val, (void *)cb->data, val);
+}
+
+static unsigned char
+_ecore_getopt_parse_help(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc __UNUSED__, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (val->boolp)
+     (*val->boolp) = 1;
+   ecore_getopt_help(stdout, parser);
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_version(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (val->boolp)
+     (*val->boolp) = 1;
+   if (!parser->version)
+     {
+       _ecore_getopt_desc_print_error(desc, _("no version was defined.\n"));
+       return 0;
+     }
+   _ecore_getopt_version(stdout, parser);
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_copyright(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (val->boolp)
+     (*val->boolp) = 1;
+   if (!parser->copyright)
+     {
+       _ecore_getopt_desc_print_error(desc, _("no copyright was defined.\n"));
+       return 0;
+     }
+   _ecore_getopt_copyright(stdout, parser);
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_license(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *val, const char *arg_val __UNUSED__)
+{
+   if (val->boolp)
+     (*val->boolp) = 1;
+   if (!parser->license)
+     {
+       _ecore_getopt_desc_print_error(desc, _("no license was defined.\n"));
+       return 0;
+     }
+   _ecore_getopt_license(stdout, parser);
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_desc_handle(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, Ecore_Getopt_Value *value, const char *arg_val)
+{
+   switch (desc->action)
+     {
+      case ECORE_GETOPT_ACTION_STORE:
+        return _ecore_getopt_parse_store(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_STORE_CONST:
+        return _ecore_getopt_parse_store_const(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_STORE_TRUE:
+        return _ecore_getopt_parse_store_true(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_STORE_FALSE:
+        return _ecore_getopt_parse_store_false(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_CHOICE:
+        return _ecore_getopt_parse_choice(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_APPEND:
+        return _ecore_getopt_parse_append(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_COUNT:
+        return _ecore_getopt_parse_count(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_CALLBACK:
+        return _ecore_getopt_parse_callback(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_HELP:
+        return _ecore_getopt_parse_help(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_VERSION:
+        return _ecore_getopt_parse_version(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_COPYRIGHT:
+        return _ecore_getopt_parse_copyright(parser, desc, value, arg_val);
+      case ECORE_GETOPT_ACTION_LICENSE:
+        return _ecore_getopt_parse_license(parser, desc, value, arg_val);
+      default:
+        return 0;
+     }
+}
+
+static unsigned char
+_ecore_getopt_parse_arg_long(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc __UNUSED__, char **argv, int *idx, int *nonargs, const char *arg)
+{
+   const Ecore_Getopt_Desc *desc;
+   Ecore_Getopt_Desc_Arg_Requirement arg_req;
+   const char *arg_val;
+   int desc_idx;
+   Ecore_Getopt_Value *value;
+   unsigned char ret;
+
+   desc = _ecore_getopt_parse_find_long(parser, arg);
+   if (!desc)
+     {
+       fprintf(stderr, _("ERROR: unknown option --%s, ignored.\n"), arg);
+       if (parser->strict)
+         return 0;
+
+       (*idx)++;
+       return 1;
+     }
+
+   (*idx)++;
+
+   arg_req = _ecore_getopt_desc_arg_requirement(desc);
+   if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+     {
+       arg_val = strchr(arg, '=');
+       if (arg_val)
+         arg_val++;
+       else
+         {
+            if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
+              {
+                 arg_val = argv[*idx];
+                 (*idx)++;
+              }
+            else
+              arg_val = NULL;
+         }
+
+       if (arg_val && arg_val[0] == '\0')
+         arg_val = NULL;
+
+       if ((!arg_val) && (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
+         {
+            fprintf
+              (stderr, _("ERROR: option --%s requires an argument!\n"), arg);
+            if (parser->strict)
+              return 0;
+            return 1;
+         }
+     }
+   else
+     arg_val = NULL;
+
+   desc_idx = desc - parser->descs;
+   value = values + desc_idx;
+   ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
+   if ((!ret) && parser->strict)
+     return 0;
+
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_arg_short(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc __UNUSED__, char **argv, int *idx, int *nonargs, const char *arg)
+{
+   int run = 1;
+   while (run && (arg[0] != '\0'))
+     {
+       int opt = arg[0];
+       const Ecore_Getopt_Desc *desc;
+       Ecore_Getopt_Desc_Arg_Requirement arg_req;
+       const char *arg_val;
+       int desc_idx;
+       Ecore_Getopt_Value *value;
+       unsigned char ret;
+
+       desc = _ecore_getopt_parse_find_short(parser, arg[0]);
+       if (!desc)
+         {
+            fprintf
+              (stderr, _("ERROR: unknown option -%c, ignored.\n"), arg[0]);
+            if (parser->strict)
+              return 0;
+
+            arg++;
+            continue;
+         }
+
+       arg++;
+
+       arg_req = _ecore_getopt_desc_arg_requirement(desc);
+       if (arg_req != ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO)
+         {
+            (*idx)++;
+            run = 0;
+
+            if (arg[0] == '=')
+              arg_val = arg + 1;
+            else if (arg[0] != '\0')
+              arg_val = arg;
+            else
+              {
+                 if ((*idx < *nonargs) && (argv[*idx][0] != '-'))
+                   {
+                      arg_val = argv[*idx];
+                      (*idx)++;
+                   }
+                 else
+                   arg_val = NULL;
+              }
+
+            if (arg_val && arg_val[0] == '\0')
+              arg_val = NULL;
+
+            if ((!arg_val) &&
+                (arg_req == ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES))
+              {
+                 fprintf
+                   (stderr, _("ERROR: option -%c requires an argument!\n"),
+                    opt);
+                 if (parser->strict)
+                   return 0;
+                 return 1;
+              }
+         }
+       else
+         arg_val = NULL;
+
+       desc_idx = desc - parser->descs;
+       value = values + desc_idx;
+       ret = _ecore_getopt_desc_handle(parser, desc, value, arg_val);
+       if ((!ret) && parser->strict)
+         return 0;
+     }
+
+   if (run)
+     (*idx)++;
+
+   return 1;
+}
+
+static unsigned char
+_ecore_getopt_parse_arg(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv, int *idx, int *nonargs)
+{
+   char *arg = argv[*idx];
+
+   if (arg[0] != '-')
+     {
+       char **dst, **src, **src_end;
+
+       dst = argv + *idx;
+       src = dst + 1;
+       src_end = src + *nonargs - *idx - 1;
+
+       for (; src < src_end; src++, dst++)
+         *dst = *src;
+
+       *dst = arg;
+       (*nonargs)--;
+       return 1;
+     }
+
+   if (arg[1] == '-')
+     return _ecore_getopt_parse_arg_long
+       (parser, values, argc, argv, idx, nonargs, arg + 2);
+   else
+     return _ecore_getopt_parse_arg_short
+       (parser, values, argc, argv, idx, nonargs, arg + 1);
+}
+
+static const Ecore_Getopt_Desc *
+_ecore_getopt_parse_find_short_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   const char c = orig->shortname;
+
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+       if (desc == orig)
+         return NULL;
+
+       if (c == desc->shortname)
+         return desc;
+     }
+
+   return NULL;
+}
+
+static const Ecore_Getopt_Desc *
+_ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *orig)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   const char *name = orig->longname;
+
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+       if (desc == orig)
+         return NULL;
+
+       if (desc->longname && (strcmp(name, desc->longname) == 0))
+         return desc;
+     }
+
+   return NULL;
+}
+
+/**
+ * Check parser for duplicate entries, print them out.
+ *
+ * @return 1 if there are duplicates, 0 otherwise.
+ */
+unsigned char
+ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+       if (desc->shortname)
+        {
+          const Ecore_Getopt_Desc *other;
+          other = _ecore_getopt_parse_find_short_other(parser, desc);
+          if (other)
+            {
+               _ecore_getopt_desc_print_error
+                 (desc, "short name -%c already exists.", desc->shortname);
+
+               if (other->longname)
+                 fprintf(stderr, " Other is --%s.\n", other->longname);
+               else
+                 fputc('\n', stderr);
+               return 1;
+            }
+        }
+
+       if (desc->longname)
+        {
+          const Ecore_Getopt_Desc *other;
+          other = _ecore_getopt_parse_find_long_other(parser, desc);
+          if (other)
+            {
+               _ecore_getopt_desc_print_error
+                 (desc, "long name --%s already exists.", desc->longname);
+
+               if (other->shortname)
+                 fprintf(stderr, " Other is -%c.\n", other->shortname);
+               else
+                 fputc('\n', stderr);
+               return 1;
+            }
+        }
+     }
+   return 0;
+}
+
+static const Ecore_Getopt_Desc *
+_ecore_getopt_find_help(const Ecore_Getopt *parser)
+{
+   const Ecore_Getopt_Desc *desc = parser->descs;
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     if (desc->action == ECORE_GETOPT_ACTION_HELP)
+       return desc;
+   return NULL;
+}
+
+/**
+ * Parse command line parameters.
+ *
+ * Walks the command line parameters and parse them based on @a parser
+ * description, doing actions based on @c parser->descs->action, like
+ * showing help text, license, copyright, storing values in values and
+ * so on.
+ *
+ * It is expected that values is of the same size than @c parser->descs,
+ * options that do not need a value it will be left untouched.
+ *
+ * All values are expected to be initialized before use. Options with
+ * action @c ECORE_GETOPT_ACTION_STORE and non required arguments
+ * (others than @c ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES), are expected
+ * to provide a value in @c def to be used.
+ *
+ * The following actions will store 1 on value as a boolean
+ * (@c value->boolp) if it's not NULL to indicate these actions were executed:
+ *   - @c ECORE_GETOPT_ACTION_HELP
+ *   - @c ECORE_GETOPT_ACTION_VERSION
+ *   - @c ECORE_GETOPT_ACTION_COPYRIGHT
+ *   - @c ECORE_GETOPT_ACTION_LICENSE
+ *
+ * Just @c ECORE_GETOPT_ACTION_APPEND will allocate memory and thus
+ * need to be freed. For consistency between all of appended subtypes,
+ * @c eina_list->data will contain an allocated memory with the value,
+ * that is, for @c ECORE_GETOPT_TYPE_STR it will contain a copy of the
+ * argument, @c ECORE_GETOPT_TYPE_INT a pointer to an allocated
+ * integer and so on.
+ *
+ * If parser is in strict mode (see @c Ecore_Getopt->strict), then any
+ * error will abort parsing and -1 is returned. Otherwise it will try
+ * to continue as far as possible.
+ *
+ * This function may reorder @a argv elements.
+ *
+ * Translation of help strings (description), metavar, usage, license
+ * and copyright may be translated, standard/global gettext() call
+ * will be applied on them if ecore was compiled with such support.
+ *
+ * @param parser description of how to work.
+ * @param value where to store values, it is assumed that this is a vector
+ *        of the same size as @c parser->descs. Values should be previously
+ *        initialized.
+ * @param argc how many elements in @a argv. If not provided it will be
+ *        retrieved with ecore_app_args_get().
+ * @param argv command line parameters.
+ *
+ * @return index of first non-option parameter or -1 on error.
+ */
+int
+ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv)
+{
+   int i, nonargs;
+
+   if (!parser)
+     {
+       fputs(_("ERROR: no parser provided.\n"), stderr);
+       return -1;
+     }
+   if (!values)
+     {
+       fputs(_("ERROR: no values provided.\n"), stderr);
+       return -1;
+     }
+
+   if ((argc < 1) || (argv == NULL))
+     ecore_app_args_get(&argc, &argv);
+
+   if (argc < 1)
+     {
+       fputs(_("ERROR: no arguments provided.\n"), stderr);
+       return -1;
+     }
+
+   if (argv[0] != NULL)
+     prog = argv[0];
+   else
+     prog = parser->prog;
+
+   nonargs = _ecore_getopt_parse_find_nonargs_base(parser, argc, argv);
+   if (nonargs < 0)
+     goto error;
+
+   if (nonargs > argc)
+     nonargs = argc;
+
+   i = 1;
+   while (i < nonargs)
+     if (!_ecore_getopt_parse_arg(parser, values, argc, argv, &i, &nonargs))
+       goto error;
+
+   return nonargs;
+
+ error:
+   {
+      const Ecore_Getopt_Desc *help;
+      fputs(_("ERROR: invalid options found."), stderr);
+
+      help = _ecore_getopt_find_help(parser);
+      if (!help)
+       fputc('\n', stderr);
+      else if (help->longname)
+       fprintf(stderr, _(" See --%s.\n"), help->longname);
+      else
+       fprintf(stderr, _(" See -%c.\n"), help->shortname);
+   }
+
+   return -1;
+}
+
+/**
+ * Utility to free list and nodes allocated by @a ECORE_GETOPT_ACTION_APPEND.
+ *
+ * @param list pointer to list to be freed.
+ * @return always NULL, so you can easily make your list head NULL.
+ */
+Eina_List *
+ecore_getopt_list_free(Eina_List *list)
+{
+   void *data;
+
+   EINA_LIST_FREE(list, data)
+     free(data);
+   return NULL;
+}
+
+/**
+ * Helper ecore_getopt callback to parse geometry (x:y:w:h).
+ *
+ * Storage must be a pointer to @c Eina_Rectangle and will be used to
+ * store the four values passed in the given string.
+ *
+ * @c callback_data value is ignored, you can safely use @c NULL.
+ */
+unsigned char
+ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str, void *data __UNUSED__, Ecore_Getopt_Value *storage)
+{
+   Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
+
+   if (sscanf(str, "%d:%d:%d:%d", &v->x, &v->y, &v->w, &v->h) != 4)
+     {
+       fprintf(stderr, _("ERROR: incorrect geometry value '%s'\n"), str);
+       return 0;
+     }
+
+   return 1;
+}
+
+/**
+ * Helper ecore_getopt callback to parse geometry size (WxH).
+ *
+ * Storage must be a pointer to @c Eina_Rectangle and will be used to
+ * store the two values passed in the given string and 0 in the x and y
+ * fields.
+ *
+ * @c callback_data value is ignored, you can safely use @c NULL.
+ */
+unsigned char
+ecore_getopt_callback_size_parse(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str, void *data __UNUSED__, Ecore_Getopt_Value *storage)
+{
+   Eina_Rectangle *v = (Eina_Rectangle *)storage->ptrp;
+
+   if (sscanf(str, "%dx%d", &v->w, &v->h) != 2)
+     {
+       fprintf(stderr, _("ERROR: incorrect size value '%s'\n"), str);
+       return 0;
+     }
+   v->x = 0;
+   v->y = 0;
+
+   return 1;
+}
diff --git a/src/lib/ecore/ecore_glib.c b/src/lib/ecore/ecore_glib.c
new file mode 100644 (file)
index 0000000..0b1a39c
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#ifdef HAVE_GLIB
+#include <glib.h>
+
+static Eina_Bool _ecore_glib_active = EINA_FALSE;
+static int (*_ecore_glib_select_original)(int, fd_set*, fd_set*, fd_set*, struct timeval *);
+static GCond *_ecore_glib_cond = NULL;
+static GPollFD *_ecore_glib_fds = NULL;
+static size_t _ecore_glib_fds_size = 0;
+static const size_t ECORE_GLIB_FDS_INITIAL = 128;
+static const size_t ECORE_GLIB_FDS_STEP = 8;
+static const size_t ECORE_GLIB_FDS_MAX_FREE = 256;
+
+static Eina_Bool
+_ecore_glib_fds_resize(size_t size)
+{
+   void *tmp = realloc(_ecore_glib_fds, sizeof(GPollFD) * size);
+   
+   if (!tmp)
+     {
+       ERR("Could not realloc from %zu to %zu buckets.",
+           _ecore_glib_fds_size, size);
+       return EINA_FALSE;
+     }
+   
+   _ecore_glib_fds = tmp;
+   _ecore_glib_fds_size = size;
+   return EINA_TRUE;
+}
+
+static int
+_ecore_glib_context_query(GMainContext *ctx, int priority, int *p_timer)
+{
+   int reqfds;
+
+   if (_ecore_glib_fds_size == 0)
+     {
+        if (!_ecore_glib_fds_resize(ECORE_GLIB_FDS_INITIAL)) return -1;
+     }
+   
+   while (1)
+     {
+        size_t size;
+        
+        reqfds = g_main_context_query
+         (ctx, priority, p_timer, _ecore_glib_fds, _ecore_glib_fds_size);
+        if (reqfds <= (int)_ecore_glib_fds_size) break;
+
+        size = (1 + reqfds / ECORE_GLIB_FDS_STEP) * ECORE_GLIB_FDS_STEP;
+        if (!_ecore_glib_fds_resize(size)) return -1;
+     }
+
+   if (reqfds + ECORE_GLIB_FDS_MAX_FREE < _ecore_glib_fds_size)
+     {
+        size_t size;
+
+       size = (1 + reqfds / ECORE_GLIB_FDS_MAX_FREE) * ECORE_GLIB_FDS_MAX_FREE;
+        _ecore_glib_fds_resize(size);
+     }
+
+   return reqfds;
+}
+
+static int
+_ecore_glib_context_poll_from(const GPollFD *pfds, int count, fd_set *rfds, fd_set *wfds, fd_set *efds)
+{
+   const GPollFD *itr = pfds, *itr_end = pfds + count;
+   int glib_fds = -1;
+   
+   for (; itr < itr_end; itr++)
+     {
+        if (glib_fds < itr->fd)
+         glib_fds = itr->fd;
+
+        if (itr->events & G_IO_IN)
+         FD_SET(itr->fd, rfds);
+        if (itr->events & G_IO_OUT)
+         FD_SET(itr->fd, wfds);
+        if (itr->events & (G_IO_HUP | G_IO_ERR))
+         FD_SET(itr->fd, efds);
+     }
+
+   return glib_fds + 1;
+}
+
+static int
+_ecore_glib_context_poll_to(GPollFD *pfds, int count, const fd_set *rfds, const fd_set *wfds, const fd_set *efds, int ready)
+{
+   GPollFD *itr = pfds, *itr_end = pfds + count;
+   
+   for (; itr < itr_end && ready > 0; itr++)
+     {
+        itr->revents = 0;
+        if (FD_ISSET(itr->fd, rfds))
+         {
+            itr->revents |= G_IO_IN;
+            ready--;
+         }
+        if (FD_ISSET(itr->fd, wfds))
+         {
+            itr->revents |= G_IO_OUT;
+            ready--;
+         }
+        if (FD_ISSET(itr->fd, efds))
+         {
+            itr->revents |= G_IO_ERR;
+            ready--;
+         }
+     }
+   return ready;
+}
+
+static int
+_ecore_glib_select__locked(GMainContext *ctx, int ecore_fds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *ecore_timeout)
+{
+   int priority, maxfds, glib_fds, reqfds, reqtimeout, ret;
+   struct timeval *timeout, glib_timeout;
+
+   g_main_context_prepare(ctx, &priority);
+   reqfds = _ecore_glib_context_query(ctx, priority, &reqtimeout);
+   if (reqfds < 0) goto error;
+
+   glib_fds = _ecore_glib_context_poll_from
+     (_ecore_glib_fds, reqfds, rfds, wfds, efds);
+
+   if (reqtimeout == -1)
+     timeout = ecore_timeout;
+   else
+     {
+        glib_timeout.tv_sec = reqtimeout / 1000;
+        glib_timeout.tv_usec = (reqtimeout % 1000) * 1000;
+        
+        if (!ecore_timeout || timercmp(ecore_timeout, &glib_timeout, >))
+          timeout = &glib_timeout;
+        else
+          timeout = ecore_timeout;
+     }
+
+   maxfds = (ecore_fds >= glib_fds) ? ecore_fds : glib_fds;
+   ret = _ecore_glib_select_original(maxfds, rfds, wfds, efds, timeout);
+
+   ret = _ecore_glib_context_poll_to
+     (_ecore_glib_fds, reqfds, rfds, wfds, efds, ret);
+
+   if (g_main_context_check(ctx, priority, _ecore_glib_fds, reqfds))
+     g_main_context_dispatch(ctx);
+
+   return ret;
+
+ error:
+   return _ecore_glib_select_original
+     (ecore_fds, rfds, wfds, efds, ecore_timeout);
+}
+
+static int
+_ecore_glib_select(int ecore_fds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *ecore_timeout)
+{
+   GStaticMutex lock = G_STATIC_MUTEX_INIT;
+   GMutex *mutex = g_static_mutex_get_mutex(&lock);
+   GMainContext *ctx = g_main_context_default();
+   int ret;
+
+   if (g_main_context_acquire(ctx))
+     g_mutex_lock(mutex);
+   else
+     {
+       if (!_ecore_glib_cond)
+         _ecore_glib_cond = g_cond_new();
+
+       while (!g_main_context_wait(ctx, _ecore_glib_cond, mutex))
+         g_thread_yield();
+     }
+
+   ret = _ecore_glib_select__locked
+     (ctx, ecore_fds, rfds, wfds, efds, ecore_timeout);
+
+   g_mutex_unlock(mutex);
+   g_main_context_release(ctx);
+
+   return ret;
+}
+#endif
+
+void
+_ecore_glib_init(void)
+{
+}
+
+void
+_ecore_glib_shutdown(void)
+{
+#ifdef HAVE_GLIB
+   if (!_ecore_glib_active) return;
+   _ecore_glib_active = EINA_FALSE;
+
+   if (ecore_main_loop_select_func_get() == _ecore_glib_select)
+     ecore_main_loop_select_func_set(_ecore_glib_select_original);
+   
+   if (_ecore_glib_fds)
+     {
+       free(_ecore_glib_fds);
+       _ecore_glib_fds = NULL;
+     }
+   _ecore_glib_fds_size = 0;
+
+   if (_ecore_glib_cond)
+     {
+       g_cond_free(_ecore_glib_cond);
+       _ecore_glib_cond = NULL;
+     }
+#endif
+}
+
+/**
+ * Request ecore to integrate GLib's main loop.
+ *
+ * This will add a small overhead during every main loop interaction
+ * by checking glib's default main context (used by its main loop). If
+ * it have events to be checked (timers, file descriptors or idlers),
+ * then these will be polled alongside with Ecore's own events, then
+ * dispatched before Ecore's. This is done by calling
+ * ecore_main_loop_select_func_set().
+ *
+ * This will cooperate with previously set
+ * ecore_main_loop_select_func_set() by calling the old
+ * function. Similarly, if you want to override
+ * ecore_main_loop_select_func_set() after main loop is integrated,
+ * call the new select function set by this call (get it by calling
+ * ecore_main_loop_select_func_get() right after
+ * ecore_main_loop_glib_integrate()).
+ *
+ * This is useful to use GMainLoop libraries, like GTK, GUPnP,
+ * LibSoup, GConf and more. Adobe Flash plugin and other plugins
+ * systems depend on this as well.
+ *
+ * Once initialized/integrated, it will be valid until Ecore is
+ * completely shut down.
+ *
+ * @note this is only available if Ecore was compiled with GLib support.
+ *
+ * @return @c EINA_TRUE on success of @c EINA_FALSE if it failed,
+ *         likely no GLib support in Ecore.
+ */
+EAPI Eina_Bool
+ecore_main_loop_glib_integrate(void)
+{
+#ifdef HAVE_GLIB
+   void *func;
+
+   if (_ecore_glib_active) return EINA_TRUE;
+   func = ecore_main_loop_select_func_get();
+   if (func == _ecore_glib_select) return EINA_TRUE;
+   _ecore_glib_select_original = func;
+   ecore_main_loop_select_func_set(_ecore_glib_select);
+   _ecore_glib_active = EINA_TRUE;
+   return EINA_TRUE;
+#else
+   fputs("ERROR: no glib support in ecore.\n", stderr);
+   return EINA_FALSE;
+#endif
+}
+
+Eina_Bool _ecore_glib_always_integrate = 1;
+
+/**
+ * Disable always integrating glib
+ * 
+ * If ecore is compiled with --enable-glib-integration-always (to always
+ * call ecore_main_loop_glib_integrate() when ecore_init() is called), then
+ * calling this before calling ecore_init() will disable the integration.
+ * This is for apps that explicitly do not want this to happen for whatever
+ * reasons they may have.
+ */
+EAPI void
+ecore_main_loop_glib_always_integrate_disable(void)
+{
+   _ecore_glib_always_integrate = 0;
+}
diff --git a/src/lib/ecore/ecore_idle_enterer.c b/src/lib/ecore/ecore_idle_enterer.c
new file mode 100644 (file)
index 0000000..2f9a592
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Idle_Enterer
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int        (*func) (void *data);
+   void        *data;
+   int          references;
+   Eina_Bool    delete_me : 1;
+};
+
+
+static Ecore_Idle_Enterer *idle_enterers = NULL;
+static Ecore_Idle_Enterer *idle_enterer_current = NULL;
+static int                 idle_enterers_delete_me = 0;
+
+/**
+ * Add an idle enterer handler.
+ * @param   func The function to call when entering an idle state.
+ * @param   data The data to be passed to the @p func call
+ * @return  A handle to the idle enterer callback if successful.  Otherwise,
+ *          NULL is returned.
+ * @ingroup Idle_Group
+ */
+EAPI Ecore_Idle_Enterer *
+ecore_idle_enterer_add(int (*func) (void *data), const void *data)
+{
+   Ecore_Idle_Enterer *ie;
+
+   if (!func) return NULL;
+   ie = calloc(1, sizeof(Ecore_Idle_Enterer));
+   if (!ie) return NULL;
+   ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
+   ie->func = func;
+   ie->data = (void *)data;
+   idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_append(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
+   return ie;
+}
+
+/**
+ * Add an idle enterer handler at the start of the list so it gets called earlier than others.
+ * @param   func The function to call when entering an idle state.
+ * @param   data The data to be passed to the @p func call
+ * @return  A handle to the idle enterer callback if successful.  Otherwise,
+ *          NULL is returned.
+ * @ingroup Idle_Group
+ */
+EAPI Ecore_Idle_Enterer *
+ecore_idle_enterer_before_add(int (*func) (void *data), const void *data)
+{
+   Ecore_Idle_Enterer *ie;
+
+   if (!func) return NULL;
+   ie = calloc(1, sizeof(Ecore_Idle_Enterer));
+   if (!ie) return NULL;
+   ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
+   ie->func = func;
+   ie->data = (void *)data;
+   idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_prepend(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
+   return ie;
+}
+
+/**
+ * Delete an idle enterer callback.
+ * @param   idle_enterer The idle enterer to delete
+ * @return  The data pointer passed to the idler enterer callback on success.
+ *          NULL otherwise.
+ * @ingroup Idle_Group
+ */
+EAPI void *
+ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer)
+{
+   if (!ECORE_MAGIC_CHECK(idle_enterer, ECORE_MAGIC_IDLE_ENTERER))
+     {
+       ECORE_MAGIC_FAIL(idle_enterer, ECORE_MAGIC_IDLE_ENTERER,
+                        "ecore_idle_enterer_del");
+       return NULL;
+     }
+   idle_enterer->delete_me = 1;
+   idle_enterers_delete_me = 1;
+   return idle_enterer->data;
+}
+
+void
+_ecore_idle_enterer_shutdown(void)
+{
+   Ecore_Idle_Enterer *ie;
+   while ((ie = idle_enterers))
+     {
+       idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_remove(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(idle_enterers));
+       ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+       free(ie);
+     }
+   idle_enterers_delete_me = 0;
+   idle_enterer_current = NULL;
+}
+
+void
+_ecore_idle_enterer_call(void)
+{
+   if (!idle_enterer_current)
+     {
+       /* regular main loop, start from head */
+       idle_enterer_current = idle_enterers;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       idle_enterer_current =
+         (Ecore_Idle_Enterer *)EINA_INLIST_GET(idle_enterer_current)->next;
+     }
+
+   while (idle_enterer_current)
+     {
+       Ecore_Idle_Enterer *ie = (Ecore_Idle_Enterer *)idle_enterer_current;
+       if (!ie->delete_me)
+         {
+            ie->references++;
+            if (!ie->func(ie->data)) ecore_idle_enterer_del(ie);
+            ie->references--;
+         }
+       if (idle_enterer_current) /* may have changed in recursive main loops */
+         idle_enterer_current =
+           (Ecore_Idle_Enterer *)EINA_INLIST_GET(idle_enterer_current)->next;
+     }
+   if (idle_enterers_delete_me)
+     {
+        Ecore_Idle_Enterer *l;
+       int deleted_idler_enterers_in_use = 0;
+
+       for (l = idle_enterers; l;)
+         {
+            Ecore_Idle_Enterer *ie = l;
+            l = (Ecore_Idle_Enterer *) EINA_INLIST_GET(l)->next;
+            if (ie->delete_me)
+              {
+                 if (ie->references)
+                   {
+                      deleted_idler_enterers_in_use++;
+                      continue;
+                   }
+
+                 idle_enterers = (Ecore_Idle_Enterer *) eina_inlist_remove(EINA_INLIST_GET(idle_enterers), EINA_INLIST_GET(ie));
+                 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+                 free(ie);
+              }
+         }
+       if (!deleted_idler_enterers_in_use)
+         idle_enterers_delete_me = 0;
+     }
+}
+
+int
+_ecore_idle_enterer_exist(void)
+{
+   if (idle_enterers) return 1;
+   return 0;
+}
diff --git a/src/lib/ecore/ecore_idle_exiter.c b/src/lib/ecore/ecore_idle_exiter.c
new file mode 100644 (file)
index 0000000..1d5c6ce
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Idle_Exiter
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int        (*func) (void *data);
+   void        *data;
+   int          references;
+   Eina_Bool    delete_me : 1;
+};
+
+
+static Ecore_Idle_Exiter *idle_exiters = NULL;
+static Ecore_Idle_Exiter *idle_exiter_current = NULL;
+static int                idle_exiters_delete_me = 0;
+
+/**
+ * Add an idle exiter handler.
+ * @param func The function to call when exiting an idle state.
+ * @param data The data to be passed to the @p func call
+ * @return A handle to the idle exiter callback on success.  NULL otherwise.
+ * @ingroup Idle_Group
+ */
+EAPI Ecore_Idle_Exiter *
+ecore_idle_exiter_add(int (*func) (void *data), const void *data)
+{
+   Ecore_Idle_Exiter *ie;
+
+   if (!func) return NULL;
+   ie = calloc(1, sizeof(Ecore_Idle_Exiter));
+   if (!ie) return NULL;
+   ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_EXITER);
+   ie->func = func;
+   ie->data = (void *)data;
+   idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_append(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
+   return ie;
+}
+
+/**
+ * Delete an idle exiter handler from the list to be run on exiting idle state.
+ * @param idle_exiter The idle exiter to delete
+ * @return The data pointer that was being being passed to the handler if
+ *         successful.  NULL otherwise.
+ * @ingroup Idle_Group
+ */
+EAPI void *
+ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter)
+{
+   if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER))
+     {
+       ECORE_MAGIC_FAIL(idle_exiter, ECORE_MAGIC_IDLE_EXITER,
+                        "ecore_idle_exiter_del");
+       return NULL;
+     }
+   idle_exiter->delete_me = 1;
+   idle_exiters_delete_me = 1;
+   return idle_exiter->data;
+}
+
+void
+_ecore_idle_exiter_shutdown(void)
+{
+   Ecore_Idle_Exiter *ie;
+   while ((ie = idle_exiters))
+     {
+       idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(idle_exiters));
+       ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+       free(ie);
+     }
+   idle_exiters_delete_me = 0;
+   idle_exiter_current = NULL;
+}
+
+void
+_ecore_idle_exiter_call(void)
+{
+   if (!idle_exiter_current)
+     {
+       /* regular main loop, start from head */
+       idle_exiter_current = idle_exiters;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       idle_exiter_current =
+         (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
+     }
+
+   while (idle_exiter_current)
+     {
+       Ecore_Idle_Exiter *ie = (Ecore_Idle_Exiter *)idle_exiter_current;
+       if (!ie->delete_me)
+         {
+            ie->references++;
+            if (!ie->func(ie->data)) ecore_idle_exiter_del(ie);
+            ie->references--;
+         }
+       if (idle_exiter_current) /* may have changed in recursive main loops */
+         idle_exiter_current =
+           (Ecore_Idle_Exiter *)EINA_INLIST_GET(idle_exiter_current)->next;
+     }
+   if (idle_exiters_delete_me)
+     {
+       Ecore_Idle_Exiter *l;
+       int deleted_idler_exiters_in_use = 0;
+
+       for (l = idle_exiters; l;)
+         {
+            Ecore_Idle_Exiter *ie = l;
+
+            l = (Ecore_Idle_Exiter *) EINA_INLIST_GET(l)->next;
+            if (ie->delete_me)
+              {
+                 if (ie->references)
+                   {
+                      deleted_idler_exiters_in_use++;
+                      continue;
+                   }
+
+                 idle_exiters = (Ecore_Idle_Exiter *) eina_inlist_remove(EINA_INLIST_GET(idle_exiters), EINA_INLIST_GET(ie));
+                 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+                 free(ie);
+              }
+         }
+       if (!deleted_idler_exiters_in_use)
+         idle_exiters_delete_me = 0;
+     }
+}
+
+int
+_ecore_idle_exiter_exist(void)
+{
+   if (idle_exiters) return 1;
+   return 0;
+}
diff --git a/src/lib/ecore/ecore_idler.c b/src/lib/ecore/ecore_idler.c
new file mode 100644 (file)
index 0000000..6df9ad0
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Idler
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int        (*func) (void *data);
+   void        *data;
+   int          references;
+   Eina_Bool    delete_me : 1;
+};
+
+
+static Ecore_Idler *idlers = NULL;
+static Ecore_Idler *idler_current = NULL;
+static int          idlers_delete_me = 0;
+
+/**
+ * Add an idler handler.
+ * @param  func The function to call when idling.
+ * @param  data The data to be passed to this @p func call.
+ * @return A idler handle if successfully added.  NULL otherwise.
+ * @ingroup Idle_Group
+ *
+ * Add an idler handle to the event loop, returning a handle on success and
+ * NULL otherwise.  The function @p func will be called repeatedly while
+ * no other events are ready to be processed, as long as it returns 1
+ * (or ECORE_CALLBACK_RENEW). A return of 0 (or ECORE_CALLBACK_CANCEL) deletes
+ * the idler.
+ *
+ * Idlers are useful for progressively prossessing data without blocking.
+ */
+EAPI Ecore_Idler *
+ecore_idler_add(int (*func) (void *data), const void *data)
+{
+   Ecore_Idler *ie;
+
+   if (!func) return NULL;
+   ie = calloc(1, sizeof(Ecore_Idler));
+   if (!ie) return NULL;
+   ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER);
+   ie->func = func;
+   ie->data = (void *)data;
+   idlers = (Ecore_Idler *) eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+   return ie;
+}
+
+/**
+ * Delete an idler callback from the list to be executed.
+ * @param  idler The handle of the idler callback to delete
+ * @return The data pointer passed to the idler callback on success.  NULL
+ *         otherwise.
+ * @ingroup Idle_Group
+ */
+EAPI void *
+ecore_idler_del(Ecore_Idler *idler)
+{
+   if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER))
+     {
+       ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER,
+                        "ecore_idler_del");
+       return NULL;
+     }
+   idler->delete_me = 1;
+   idlers_delete_me = 1;
+   return idler->data;
+}
+
+void
+_ecore_idler_shutdown(void)
+{
+   Ecore_Idler *ie;
+   while ((ie = idlers))
+     {
+       idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
+       ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+       free(ie);
+     }
+   idlers_delete_me = 0;
+   idler_current = NULL;
+}
+
+int
+_ecore_idler_call(void)
+{
+   if (!idler_current)
+     {
+       /* regular main loop, start from head */
+       idler_current = idlers;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
+     }
+
+   while (idler_current)
+     {
+       Ecore_Idler *ie = (Ecore_Idler *)idler_current;
+       if (!ie->delete_me)
+         {
+            ie->references++;
+            if (!ie->func(ie->data)) ecore_idler_del(ie);
+            ie->references--;
+         }
+       if (idler_current) /* may have changed in recursive main loops */
+         idler_current = (Ecore_Idler *)EINA_INLIST_GET(idler_current)->next;
+     }
+   if (idlers_delete_me)
+     {
+       Ecore_Idler *l;
+       int deleted_idlers_in_use = 0;
+       for (l = idlers; l;)
+         {
+            Ecore_Idler *ie = l;
+            l = (Ecore_Idler *) EINA_INLIST_GET(l)->next;
+            if (ie->delete_me)
+              {
+                 if (ie->references)
+                   {
+                      deleted_idlers_in_use++;
+                      continue;
+                   }
+
+                 idlers = (Ecore_Idler *) eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+                 ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE);
+                 free(ie);
+              }
+         }
+       if (!deleted_idlers_in_use)
+         idlers_delete_me = 0;
+     }
+   if (idlers) return 1;
+   return 0;
+}
+
+int
+_ecore_idler_exist(void)
+{
+   if (idlers) return 1;
+   return 0;
+}
diff --git a/src/lib/ecore/ecore_job.c b/src/lib/ecore/ecore_job.c
new file mode 100644 (file)
index 0000000..0557a69
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+static int _ecore_job_event_handler(void *data, int type, void *ev);
+static void _ecore_job_event_free(void *data, void *ev);
+
+static int ecore_event_job_type = 0;
+static Ecore_Event_Handler* _ecore_job_handler = NULL;
+
+struct _Ecore_Job
+{
+   ECORE_MAGIC;
+   Ecore_Event  *event;
+   void        (*func) (void *data);
+   void         *data;
+};
+
+void
+_ecore_job_init(void)
+{
+   ecore_event_job_type = ecore_event_type_new();
+   _ecore_job_handler = ecore_event_handler_add(ecore_event_job_type, _ecore_job_event_handler, NULL);
+}
+
+void
+_ecore_job_shutdown(void)
+{
+   ecore_event_handler_del(_ecore_job_handler);
+   _ecore_job_handler = NULL;
+}
+
+/**
+ * Add a job to the event queue.
+ * @param   func The function to call when the job gets handled.
+ * @param   data Data pointer to be passed to the job function when the job is
+ *               handled.
+ * @return  The handle of the job.  @c NULL is returned if the job could not be
+ *          added to the queue.
+ * @ingroup Ecore_Job_Group
+ * @note    Once the job has been executed, the job handle is invalid.
+ */
+EAPI Ecore_Job *
+ecore_job_add(void (*func) (void *data), const void *data)
+{
+   Ecore_Job *job;
+   
+   if (!func) return NULL;
+
+   job = calloc(1, sizeof(Ecore_Job));
+   if (!job) return NULL;
+   ECORE_MAGIC_SET(job, ECORE_MAGIC_JOB);
+   job->event = ecore_event_add(ecore_event_job_type, job, _ecore_job_event_free, NULL);
+   if (!job->event)
+     {
+       free(job);
+       return NULL;
+     }
+   job->func = func;
+   job->data = (void *)data;
+   return job;
+}
+
+/**
+ * Delete a queued job that has not yet been executed.
+ * @param   job  Handle of the job to delete.
+ * @return  The data pointer that was to be passed to the job.
+ * @ingroup Ecore_Job_Group
+ */
+EAPI void *
+ecore_job_del(Ecore_Job *job)
+{
+   void *data;
+   
+   if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_JOB))
+     {
+       ECORE_MAGIC_FAIL(job, ECORE_MAGIC_JOB,
+                        "ecore_job_del");
+       return NULL;
+     }
+   data = job->data;
+   ECORE_MAGIC_SET(job, ECORE_MAGIC_NONE);
+   ecore_event_del(job->event);
+   return data;
+}
+
+static int
+_ecore_job_event_handler(void *data __UNUSED__, int type __UNUSED__, void *ev)
+{
+   Ecore_Job *job;
+   
+   job = ev;
+   job->func(job->data);
+   return 0;
+}
+
+static void
+_ecore_job_event_free(void *data __UNUSED__, void *ev)
+{
+   free(ev);
+}
diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c
new file mode 100644 (file)
index 0000000..7c53bfd
--- /dev/null
@@ -0,0 +1,1076 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <winsock2.h>
+# undef WIN32_LEAN_AND_MEAN
+# ifndef USER_TIMER_MINIMUM
+#  define USER_TIMER_MINIMUM 0x0a
+# endif
+#endif
+
+#ifdef __SUNPRO_C
+# include <ieeefp.h>
+# include <string.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef _MSC_VER
+#include <sys/time.h>
+# include <unistd.h>
+#else
+# include <float.h>
+#endif
+
+#define FIX_HZ 1
+
+#ifdef FIX_HZ
+# ifndef _MSC_VER
+#  include <sys/param.h>
+# endif
+# ifndef HZ
+#  define HZ 100
+# endif
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Fd_Handler
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int                      fd;
+   Ecore_Fd_Handler_Flags   flags;
+   int                    (*func) (void *data, Ecore_Fd_Handler *fd_handler);
+   void                    *data;
+   int                    (*buf_func) (void *data, Ecore_Fd_Handler *fd_handler);
+   void                    *buf_data;
+   void                   (*prep_func) (void *data, Ecore_Fd_Handler *fd_handler);
+   void                    *prep_data;
+   int                      references;
+   Eina_Bool                read_active : 1;
+   Eina_Bool                write_active : 1;
+   Eina_Bool                error_active : 1;
+   Eina_Bool                delete_me : 1;
+};
+
+#ifdef _WIN32
+struct _Ecore_Win32_Handler
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   HANDLE         h;
+   int          (*func) (void *data, Ecore_Win32_Handler *win32_handler);
+   void          *data;
+   int            references;
+   Eina_Bool      delete_me : 1;
+};
+#endif
+
+
+static int  _ecore_main_select(double timeout);
+static void _ecore_main_fd_handlers_cleanup(void);
+#ifndef _WIN32
+static void _ecore_main_fd_handlers_bads_rem(void);
+#endif
+static void _ecore_main_fd_handlers_call(void);
+static int  _ecore_main_fd_handlers_buf_call(void);
+static void _ecore_main_loop_iterate_internal(int once_only);
+
+#ifdef _WIN32
+static int _ecore_main_win32_select(int nfds, fd_set *readfds, fd_set *writefds,
+                                   fd_set *exceptfds, struct timeval *timeout);
+static void _ecore_main_win32_handlers_cleanup(void);
+#endif
+
+static int               in_main_loop = 0;
+static int               do_quit = 0;
+static Ecore_Fd_Handler *fd_handlers = NULL;
+static Ecore_Fd_Handler *fd_handler_current = NULL;
+static int               fd_handlers_delete_me = 0;
+#ifdef _WIN32
+static Ecore_Win32_Handler *win32_handlers = NULL;
+static Ecore_Win32_Handler *win32_handler_current = NULL;
+static int                  win32_handlers_delete_me = 0;
+#endif
+
+#ifdef _WIN32
+static int (*main_loop_select)(int , fd_set *, fd_set *, fd_set *, struct timeval *) = _ecore_main_win32_select;
+#else
+static int (*main_loop_select)(int , fd_set *, fd_set *, fd_set *, struct timeval *) = select;
+#endif
+
+static double            t1 = 0.0;
+static double            t2 = 0.0;
+
+/**
+ * @defgroup Ecore_Main_Loop_Group Main Loop Functions
+ *
+ * These functions control the Ecore event handling loop.  This loop is
+ * designed to work on embedded systems all the way to large and
+ * powerful mutli-cpu workstations.
+ *
+ * It serialises all system signals and events into a single event
+ * queue, that can be easily processed without needing to worry about
+ * concurrency.  A properly written, event-driven program using this
+ * kind of programming does not need threads.  It makes the program very
+ * robust and easy to follow.
+ *
+ * Here is an example of simple program and its basic event loop flow:
+ * @image html prog_flow.png
+ *
+ * For examples of setting up and using a main loop, see
+ * @ref event_handler_example.c and @ref timer_example.c.
+ */
+
+/**
+ * Runs a single iteration of the main loop to process everything on the
+ * queue.
+ * @ingroup Ecore_Main_Loop_Group
+ */
+EAPI void
+ecore_main_loop_iterate(void)
+{
+   _ecore_main_loop_iterate_internal(1);
+}
+
+/**
+ * Runs the application main loop.
+ *
+ * This function will not return until @ref ecore_main_loop_quit is called.
+ *
+ * @ingroup Ecore_Main_Loop_Group
+ */
+EAPI void
+ecore_main_loop_begin(void)
+{
+   in_main_loop++;
+   for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0);
+   do_quit = 0;
+   in_main_loop--;
+}
+
+/**
+ * Quits the main loop once all the events currently on the queue have
+ * been processed.
+ * @ingroup Ecore_Main_Loop_Group
+ */
+EAPI void
+ecore_main_loop_quit(void)
+{
+   do_quit = 1;
+}
+
+/**
+ * Sets the function to use when monitoring multiple file descriptors,
+ * and waiting until one of more of the file descriptors before ready
+ * for some class of I/O operation.
+ *
+ * This function will be used instead of the system call select and
+ * could possible be used to integrate the Ecore event loop with an
+ * external event loop.
+ *
+ * @warning you don't know how to use, don't even try to use it.
+ *
+ * @ingroup Ecore_Main_Loop_Group
+ */
+EAPI void
+ecore_main_loop_select_func_set(int (*func)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout))
+{
+   main_loop_select = func;
+}
+
+/**
+ * Gets the select function set by ecore_select_func_set(),
+ * or the native select function if none was set.
+ *
+ * @ingroup Ecore_Main_Loop_Group
+ */
+EAPI void *
+ecore_main_loop_select_func_get(void)
+{
+   return main_loop_select;
+}
+
+/**
+ * @defgroup Ecore_FD_Handler_Group File Event Handling Functions
+ *
+ * Functions that deal with file descriptor handlers.
+ */
+
+/**
+ * Adds a callback for activity on the given file descriptor.
+ *
+ * @p func will be called during the execution of @ref ecore_main_loop_begin
+ * when the file descriptor is available for reading, or writing, or both.
+ *
+ * Normally the return value from the @p func is "zero means this handler is
+ * finished and can be deleted" as is usual for handler callbacks.  However,
+ * if the @p buf_func is supplied, then the return value from the @p func is
+ * "non zero means the handler should be called again in a tight loop".
+ *
+ * @p buf_func is called during event loop handling to check if data that has
+ * been read from the file descriptor is in a buffer and is available to
+ * read.  Some systems (notably xlib) handle their own buffering, and would
+ * otherwise not work with select().  These systems should use a @p buf_func.
+ * This is a most annoying hack, only ecore_x uses it, so refer to that for
+ * an example.  NOTE - @p func should probably return "one" always if
+ * @p buf_func is used, to avoid confusion with the other return value
+ * semantics.
+ *
+ * @param   fd       The file descriptor to watch.
+ * @param   flags    To watch it for read (@c ECORE_FD_READ) and/or
+ *                   (@c ECORE_FD_WRITE) write ability.  @c ECORE_FD_ERROR
+ *
+ * @param   func     The callback function.
+ * @param   data     The data to pass to the callback.
+ * @param   buf_func The function to call to check if any data has been
+ *                   buffered and already read from the fd.  Can be @c NULL.
+ * @param   buf_data The data to pass to the @p buf_func function.
+ * @return  A fd handler handle if successful.  @c NULL otherwise.
+ * @ingroup Ecore_FD_Handler_Group
+ */
+EAPI Ecore_Fd_Handler *
+ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data)
+{
+   Ecore_Fd_Handler *fdh;
+
+   if ((fd < 0) ||
+       (flags == 0) ||
+       (!func)) return NULL;
+
+   fdh = calloc(1, sizeof(Ecore_Fd_Handler));
+   if (!fdh) return NULL;
+   ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
+   fdh->fd = fd;
+   fdh->flags = flags;
+   fdh->read_active = 0;
+   fdh->write_active = 0;
+   fdh->error_active = 0;
+   fdh->delete_me = 0;
+   fdh->func = func;
+   fdh->data = (void *)data;
+   fdh->buf_func = buf_func;
+   fdh->buf_data = (void *)buf_data;
+   fd_handlers = (Ecore_Fd_Handler *) eina_inlist_append(EINA_INLIST_GET(fd_handlers),
+                                                        EINA_INLIST_GET(fdh));
+   return fdh;
+}
+
+#ifdef _WIN32
+EAPI Ecore_Win32_Handler *
+ecore_main_win32_handler_add(void *h,
+                             int (*func) (void *data, Ecore_Win32_Handler *wh),
+                             const void *data)
+{
+   Ecore_Win32_Handler *wh;
+
+   if (!h || !func)
+     return NULL;
+
+   wh = calloc(1, sizeof(Ecore_Win32_Handler));
+   if (!wh) return NULL;
+   ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER);
+   wh->h = (HANDLE)h;
+   wh->delete_me = 0;
+   wh->func = func;
+   wh->data = (void *)data;
+   win32_handlers = (Ecore_Win32_Handler *)eina_inlist_append(EINA_INLIST_GET(win32_handlers),
+                                                              EINA_INLIST_GET(wh));
+   return wh;
+}
+#else
+EAPI Ecore_Win32_Handler *
+ecore_main_win32_handler_add(void *h __UNUSED__,
+                             int (*func) (void *data, Ecore_Win32_Handler *wh) __UNUSED__,
+                             const void *data __UNUSED__)
+{
+   return NULL;
+}
+#endif
+
+/**
+ * Deletes the given FD handler.
+ * @param   fd_handler The given FD handler.
+ * @return  The data pointer set using @ref ecore_main_fd_handler_add,
+ *          for @p fd_handler on success.  @c NULL otherwise.
+ * @ingroup Ecore_FD_Handler_Group
+ */
+EAPI void *
+ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
+{
+   if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
+                        "ecore_main_fd_handler_del");
+       return NULL;
+     }
+   fd_handler->delete_me = 1;
+   fd_handlers_delete_me = 1;
+   return fd_handler->data;
+}
+
+#ifdef _WIN32
+EAPI void *
+ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler)
+{
+   if (!ECORE_MAGIC_CHECK(win32_handler, ECORE_MAGIC_WIN32_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(win32_handler, ECORE_MAGIC_WIN32_HANDLER,
+                        "ecore_main_win32_handler_del");
+       return NULL;
+     }
+   win32_handler->delete_me = 1;
+   win32_handlers_delete_me = 1;
+   return win32_handler->data;
+}
+#else
+EAPI void *
+ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler __UNUSED__)
+{
+   return NULL;
+}
+#endif
+
+EAPI void
+ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data)
+{
+   if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
+                        "ecore_main_fd_handler_prepare_callback_set");
+       return;
+     }
+   fd_handler->prep_func = func;
+   fd_handler->prep_data = (void *) data;
+}
+
+/**
+ * Retrieves the file descriptor that the given handler is handling.
+ * @param   fd_handler The given FD handler.
+ * @return  The file descriptor the handler is watching.
+ * @ingroup Ecore_FD_Handler_Group
+ */
+EAPI int
+ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
+{
+   if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
+                        "ecore_main_fd_handler_fd_get");
+       return -1;
+     }
+   return fd_handler->fd;
+}
+
+/**
+ * Return if read, write or error, or a combination thereof, is active on the
+ * file descriptor of the given FD handler.
+ * @param   fd_handler The given FD handler.
+ * @param   flags      The flags, @c ECORE_FD_READ, @c ECORE_FD_WRITE or
+ *                     @c ECORE_FD_ERROR to query.
+ * @return  @c 1 if any of the given flags are active. @c 0 otherwise.
+ * @ingroup Ecore_FD_Handler_Group
+ */
+EAPI int
+ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
+{
+   int ret;
+
+   if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
+                        "ecore_main_fd_handler_active_get");
+       return 0;
+     }
+   ret = 0;
+   if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = 1;
+   if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = 1;
+   if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = 1;
+   return ret;
+}
+
+/**
+ * Set what active streams the given FD handler should be monitoring.
+ * @param   fd_handler The given FD handler.
+ * @param   flags      The flags to be watching.
+ * @ingroup Ecore_FD_Handler_Group
+ */
+EAPI void
+ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
+{
+   if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
+     {
+       ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
+                        "ecore_main_fd_handler_active_set");
+       return;
+     }
+   fd_handler->flags = flags;
+}
+
+void
+_ecore_main_shutdown(void)
+{
+   if (in_main_loop)
+     {
+       ERR("\n"
+          "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n"
+          "***                 Program may crash or behave strangely now.");
+       return;
+     }
+   while (fd_handlers)
+     {
+       Ecore_Fd_Handler *fdh;
+
+       fdh = fd_handlers;
+       fd_handlers = (Ecore_Fd_Handler *) eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
+                                                             EINA_INLIST_GET(fdh));
+       ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
+       free(fdh);
+     }
+   fd_handlers_delete_me = 0;
+   fd_handler_current = NULL;
+
+#ifdef _WIN32
+   while (win32_handlers)
+     {
+       Ecore_Win32_Handler *wh;
+
+       wh = win32_handlers;
+       win32_handlers = (Ecore_Win32_Handler *) eina_inlist_remove(EINA_INLIST_GET(win32_handlers),
+                                                                   EINA_INLIST_GET(wh));
+       ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
+       free(wh);
+     }
+   win32_handlers_delete_me = 0;
+   win32_handler_current = NULL;
+#endif
+}
+
+static int
+_ecore_main_select(double timeout)
+{
+   struct timeval tv, *t;
+   fd_set         rfds, wfds, exfds;
+   int            max_fd;
+   int            ret;
+   Ecore_Fd_Handler *fdh;
+
+   t = NULL;
+   if ((!finite(timeout)) || (timeout == 0.0))  /* finite() tests for NaN, too big, too small, and infinity.  */
+     {
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+       t = &tv;
+     }
+   else if (timeout > 0.0)
+     {
+       int sec, usec;
+
+#ifdef FIX_HZ
+       timeout += (0.5 / HZ);
+       sec = (int)timeout;
+       usec = (int)((timeout - (double)sec) * 1000000);
+#else
+       sec = (int)timeout;
+       usec = (int)((timeout - (double)sec) * 1000000);
+#endif
+       tv.tv_sec = sec;
+       tv.tv_usec = usec;
+       t = &tv;
+     }
+   max_fd = 0;
+   FD_ZERO(&rfds);
+   FD_ZERO(&wfds);
+   FD_ZERO(&exfds);
+
+   /* call the prepare callback for all handlers */
+   EINA_INLIST_FOREACH(fd_handlers, fdh)
+     if (!fdh->delete_me && fdh->prep_func)
+       {
+         fdh->references++;
+         fdh->prep_func (fdh->prep_data, fdh);
+         fdh->references--;
+       }
+   EINA_INLIST_FOREACH(fd_handlers, fdh)
+     if (!fdh->delete_me)
+       {
+         if (fdh->flags & ECORE_FD_READ)
+           {
+              FD_SET(fdh->fd, &rfds);
+              if (fdh->fd > max_fd) max_fd = fdh->fd;
+           }
+         if (fdh->flags & ECORE_FD_WRITE)
+           {
+              FD_SET(fdh->fd, &wfds);
+              if (fdh->fd > max_fd) max_fd = fdh->fd;
+           }
+         if (fdh->flags & ECORE_FD_ERROR)
+           {
+              FD_SET(fdh->fd, &exfds);
+              if (fdh->fd > max_fd) max_fd = fdh->fd;
+           }
+       }
+   if (_ecore_signal_count_get()) return -1;
+
+   ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
+
+   _ecore_loop_time = ecore_time_get();
+   if (ret < 0)
+     {
+#ifndef _WIN32
+       if (errno == EINTR) return -1;
+       else if (errno == EBADF)
+          _ecore_main_fd_handlers_bads_rem();
+#endif
+     }
+   if (ret > 0)
+     {
+       EINA_INLIST_FOREACH(fd_handlers, fdh)
+         if (!fdh->delete_me)
+           {
+              if (FD_ISSET(fdh->fd, &rfds))
+                fdh->read_active = 1;
+              if (FD_ISSET(fdh->fd, &wfds))
+                fdh->write_active = 1;
+              if (FD_ISSET(fdh->fd, &exfds))
+                fdh->error_active = 1;
+           }
+       _ecore_main_fd_handlers_cleanup();
+#ifdef _WIN32
+       _ecore_main_win32_handlers_cleanup();
+#endif
+       return 1;
+     }
+   return 0;
+}
+
+#ifndef _WIN32
+static void
+_ecore_main_fd_handlers_bads_rem(void)
+{
+   Ecore_Fd_Handler *fdh;
+   Eina_Inlist *l;
+   int found = 0;
+
+   ERR("Removing bad fds");
+   for (l = EINA_INLIST_GET(fd_handlers); l; )
+     {
+       fdh = (Ecore_Fd_Handler *) l;
+       l = l->next;
+       errno = 0;
+
+       if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF))
+         {
+            ERR("Found bad fd at index %d", fdh->fd);
+            if (fdh->flags & ECORE_FD_ERROR)
+              {
+                 ERR("Fd set for error! calling user");
+                 fdh->references++;
+                 if (!fdh->func(fdh->data, fdh))
+                   {
+                      ERR("Fd function err returned 0, remove it");
+                      fdh->delete_me = 1;
+                      fd_handlers_delete_me = 1;
+                       found++;
+                   }
+                 fdh->references--;
+              }
+            else
+              {
+                 ERR("Problematic fd found at %d! setting it for delete", fdh->fd);
+                 fdh->delete_me = 1;
+                 fd_handlers_delete_me = 1;
+                  found++;
+              }
+         }
+    }
+   if (found == 0)
+     {
+#ifdef HAVE_GLIB
+        ERR("No bad fd found. Maybe a foreign fd from glib?");
+#else        
+        ERR("No bad fd found. EEEK!");
+#endif        
+     }
+   _ecore_main_fd_handlers_cleanup();
+}
+#endif
+
+static void
+_ecore_main_fd_handlers_cleanup(void)
+{
+   Ecore_Fd_Handler *fdh;
+   Eina_Inlist *l;
+   int deleted_in_use = 0;
+
+   if (!fd_handlers_delete_me) return;
+   for (l = EINA_INLIST_GET(fd_handlers); l; )
+     {
+       fdh = (Ecore_Fd_Handler *) l;
+
+       l = l->next;
+       if (fdh->delete_me)
+         {
+//          ERR("Removing fd %d", fdh->fd);
+
+            if (fdh->references)
+              {
+                 deleted_in_use++;
+                 continue;
+              }
+
+            fd_handlers = (Ecore_Fd_Handler *) eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
+                                                                  EINA_INLIST_GET(fdh));
+            ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
+            free(fdh);
+         }
+     }
+   if (!deleted_in_use)
+     fd_handlers_delete_me = 0;
+}
+
+#ifdef _WIN32
+static void
+_ecore_main_win32_handlers_cleanup(void)
+{
+   Ecore_Win32_Handler *wh;
+   Eina_Inlist *l;
+   int deleted_in_use = 0;
+
+   if (!win32_handlers_delete_me) return;
+   for (l = EINA_INLIST_GET(win32_handlers); l; )
+     {
+        wh = (Ecore_Win32_Handler *)l;
+
+        l = l->next;
+        if (wh->delete_me)
+          {
+            if (wh->references)
+              {
+                 deleted_in_use++;
+                 continue;
+              }
+
+             win32_handlers = (Ecore_Win32_Handler *)eina_inlist_remove(EINA_INLIST_GET(win32_handlers),
+                                                                        EINA_INLIST_GET(wh));
+             ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
+             free(wh);
+          }
+     }
+   if (!deleted_in_use)
+     win32_handlers_delete_me = 0;
+}
+#endif
+
+static void
+_ecore_main_fd_handlers_call(void)
+{
+   if (!fd_handler_current)
+     {
+       /* regular main loop, start from head */
+       fd_handler_current = fd_handlers;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       fd_handler_current = (Ecore_Fd_Handler *)EINA_INLIST_GET(fd_handler_current)->next;
+     }
+
+   while (fd_handler_current)
+     {
+       Ecore_Fd_Handler *fdh = fd_handler_current;
+
+       if (!fdh->delete_me)
+         {
+            if ((fdh->read_active) ||
+                (fdh->write_active) ||
+                (fdh->error_active))
+              {
+                 fdh->references++;
+                 if (!fdh->func(fdh->data, fdh))
+                   {
+                      fdh->delete_me = 1;
+                      fd_handlers_delete_me = 1;
+                   }
+                 fdh->references--;
+
+                 fdh->read_active = 0;
+                 fdh->write_active = 0;
+                 fdh->error_active = 0;
+              }
+         }
+
+       if (fd_handler_current) /* may have changed in recursive main loops */
+         fd_handler_current = (Ecore_Fd_Handler *)EINA_INLIST_GET(fd_handler_current)->next;
+     }
+}
+
+static int
+_ecore_main_fd_handlers_buf_call(void)
+{
+   Ecore_Fd_Handler *fdh;
+   int ret;
+
+   ret = 0;
+   EINA_INLIST_FOREACH(fd_handlers, fdh)
+     if (!fdh->delete_me)
+       {
+         if (fdh->buf_func)
+           {
+              fdh->references++;
+              if (fdh->buf_func(fdh->buf_data, fdh))
+                {
+                   ret |= fdh->func(fdh->data, fdh);
+                   fdh->read_active = 1;
+                }
+              fdh->references--;
+           }
+       }
+
+   return ret;
+}
+
+static void
+_ecore_main_loop_iterate_internal(int once_only)
+{
+   double next_time = -1.0;
+   int    have_event = 0;
+   int    have_signal;
+
+   in_main_loop++;
+   /* expire any timers */
+   while (_ecore_timer_call(_ecore_loop_time));
+   _ecore_timer_cleanup();
+
+   /* process signals into events .... */
+   while (_ecore_signal_count_get()) _ecore_signal_call();
+   if (_ecore_event_exist())
+     {
+        _ecore_idle_enterer_call();
+       have_event = 1;
+       _ecore_main_select(0.0);
+        _ecore_loop_time = ecore_time_get();
+        _ecore_timer_enable_new();
+       goto process_events;
+     }
+   /* call idle enterers ... */
+   if (!once_only) _ecore_idle_enterer_call();
+   else
+     {
+       have_event = have_signal = 0;
+
+       if (_ecore_main_select(0.0) > 0) have_event = 1;
+       if (_ecore_signal_count_get() > 0) have_signal = 1;
+       if (have_signal || have_event)
+          {
+             _ecore_loop_time = ecore_time_get();
+             _ecore_timer_enable_new();
+             goto process_events;
+          }
+     }
+
+   /* if these calls caused any buffered events to appear - deal with them */
+   _ecore_main_fd_handlers_buf_call();
+
+   /* if ther are any - jump to processing them */
+   if (_ecore_event_exist())
+     {
+       have_event = 1;
+       _ecore_main_select(0.0);
+        _ecore_loop_time = ecore_time_get();
+        _ecore_timer_enable_new();
+       goto process_events;
+     }
+   if (once_only)
+     {
+       _ecore_idle_enterer_call();
+       in_main_loop--;
+        _ecore_loop_time = ecore_time_get();
+        _ecore_timer_enable_new();
+       return;
+     }
+
+   if (_ecore_fps_debug)
+     {
+       t2 = ecore_time_get();
+       if ((t1 > 0.0) && (t2 > 0.0))
+         _ecore_fps_debug_runtime_add(t2 - t1);
+     }
+   start_loop:
+   /* any timers re-added as a result of these are allowed to go */
+   _ecore_timer_enable_new();
+   if (do_quit)
+     {
+        _ecore_loop_time = ecore_time_get();
+       in_main_loop--;
+        _ecore_timer_enable_new();
+       return;
+     }
+   if (!_ecore_event_exist())
+     {
+       /* init flags */
+       have_event = have_signal = 0;
+       next_time = _ecore_timer_next_get();
+       /* no timers */
+       if (next_time < 0)
+         {
+            /* no idlers */
+            if (!_ecore_idler_exist())
+              {
+                 if (_ecore_main_select(-1.0) > 0) have_event = 1;
+              }
+            /* idlers */
+            else
+              {
+                 for (;;)
+                   {
+                      if (!_ecore_idler_call()) goto start_loop;
+                      if (_ecore_event_exist()) break;
+                      if (_ecore_main_select(0.0) > 0) have_event = 1;
+                      if (_ecore_signal_count_get() > 0) have_signal = 1;
+                      if (have_event || have_signal) break;
+                      if (_ecore_timers_exists()) goto start_loop;
+                      if (do_quit) break;
+                   }
+              }
+         }
+       /* timers */
+       else
+         {
+            /* no idlers */
+            if (!_ecore_idler_exist())
+              {
+                 if (_ecore_main_select(next_time) > 0) have_event = 1;
+              }
+            /* idlers */
+            else
+              {
+                 for (;;)
+                   {
+                      if (!_ecore_idler_call()) goto start_loop;
+                      if (_ecore_event_exist()) break;
+                      if (_ecore_main_select(0.0) > 0) have_event = 1;
+                      if (_ecore_signal_count_get() > 0) have_signal = 1;
+                      if (have_event || have_signal) break;
+                      next_time = _ecore_timer_next_get();
+                      if (next_time <= 0) break;
+                      if (do_quit) break;
+                   }
+              }
+         }
+        _ecore_loop_time = ecore_time_get();
+     }
+   if (_ecore_fps_debug)
+     {
+       t1 = ecore_time_get();
+     }
+   /* we came out of our "wait state" so idle has exited */
+   if (!once_only)
+     _ecore_idle_exiter_call();
+   /* call the fd handler per fd that became alive... */
+   /* this should read or write any data to the monitored fd and then */
+   /* post events onto the ecore event pipe if necessary */
+   process_events:
+//   if (have_event) 
+   _ecore_main_fd_handlers_call();
+   _ecore_main_fd_handlers_buf_call();
+//   do
+//     {
+       /* process signals into events .... */
+       while (_ecore_signal_count_get()) _ecore_signal_call();
+       /* handle events ... */
+       _ecore_event_call();
+       _ecore_main_fd_handlers_cleanup();
+//     }
+//   while (_ecore_main_fd_handlers_buf_call());
+
+/* ok - too much optimising. let's call idle enterers more often. if we
+ * have events that place more events or jobs etc. on the event queue
+ * we may never get to call an idle enterer
+   if (once_only)
+ */
+   if (once_only)
+     _ecore_idle_enterer_call();
+   in_main_loop--;
+}
+
+#ifdef _WIN32
+static int
+_ecore_main_win32_select(int nfds __UNUSED__, fd_set *readfds, fd_set *writefds,
+                        fd_set *exceptfds, struct timeval *tv)
+{
+   HANDLE objects[MAXIMUM_WAIT_OBJECTS];
+   int    sockets[MAXIMUM_WAIT_OBJECTS];
+   Ecore_Fd_Handler *fdh;
+   Ecore_Win32_Handler *wh;
+   unsigned int objects_nbr = 0;
+   unsigned int handles_nbr = 0;
+   unsigned int events_nbr = 0;
+   DWORD  result;
+   DWORD  timeout;
+   MSG    msg;
+   unsigned int    i;
+   int    res;
+
+   /* Create an event object per socket */
+   EINA_INLIST_FOREACH(fd_handlers, fdh)
+     {
+        WSAEVENT event;
+        long network_event;
+
+        network_event = 0;
+        if(FD_ISSET(fdh->fd, readfds))
+         network_event |= FD_READ;
+        if(FD_ISSET(fdh->fd, writefds))
+         network_event |= FD_WRITE;
+        if(FD_ISSET(fdh->fd, exceptfds))
+         network_event |= FD_OOB;
+
+        if(network_event)
+         {
+             event = WSACreateEvent();
+            WSAEventSelect(fdh->fd, event, network_event);
+            objects[objects_nbr] = event;
+            sockets[events_nbr] = fdh->fd;
+            events_nbr++;
+             objects_nbr++;
+          }
+     }
+
+   /* store the HANDLEs in the objects to wait for */
+   EINA_INLIST_FOREACH(win32_handlers, wh)
+     {
+        objects[objects_nbr] = wh->h;
+        handles_nbr++;
+        objects_nbr++;
+     }
+
+   /* Empty the queue before waiting */
+   while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+     {
+       TranslateMessage(&msg);
+       DispatchMessage(&msg);
+     }
+
+   /* Wait for any message sent or posted to this queue */
+   /* or for one of the passed handles be set to signaled. */
+   if(tv == NULL)
+     timeout = INFINITE;
+   else
+     timeout = (DWORD)(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0);
+
+   if (timeout == 0) return 0;
+
+   result = MsgWaitForMultipleObjects(objects_nbr, (const HANDLE *)objects, EINA_FALSE,
+                                     timeout, QS_ALLINPUT);
+
+   FD_ZERO(readfds);
+   FD_ZERO(writefds);
+   FD_ZERO(exceptfds);
+
+   /* The result tells us the type of event we have. */
+   if (result == WAIT_FAILED)
+     {
+        char *msg;
+
+        msg = evil_last_error_get();
+        ERR(" * %s\n", msg);
+        free(msg);
+        res = -1;
+     }
+   else if (result == WAIT_TIMEOUT)
+     {
+        ERR("time out\n");
+        res = 0;
+     }
+   else if (result == (WAIT_OBJECT_0 + objects_nbr))
+     {
+        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+         {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+         }
+
+        res = 0;
+     }
+   else if ((result >= 0) && (result < WAIT_OBJECT_0 + events_nbr))
+     {
+        WSANETWORKEVENTS network_event;
+
+        WSAEnumNetworkEvents(sockets[result], objects[result], &network_event);
+
+        if(network_event.lNetworkEvents & FD_READ)
+         FD_SET(sockets[result], readfds);
+        if(network_event.lNetworkEvents & FD_WRITE)
+         FD_SET(sockets[result], writefds);
+        if(network_event.lNetworkEvents & FD_OOB)
+         FD_SET(sockets[result], exceptfds);
+
+        res = 1;
+     }
+   else if ((result >= WAIT_OBJECT_0 + events_nbr) && (result < WAIT_OBJECT_0 + objects_nbr))
+     {
+       if (!win32_handler_current)
+         {
+            /* regular main loop, start from head */
+            win32_handler_current = win32_handlers;
+         }
+       else
+         {
+            /* recursive main loop, continue from where we were */
+            win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
+         }
+
+       while (win32_handler_current)
+         {
+            wh = win32_handler_current;
+
+             if (objects[result - WAIT_OBJECT_0] == wh->h)
+               if (!wh->delete_me)
+                {
+                   wh->references++;
+                   if (!wh->func(wh->data, wh))
+                     {
+                        wh->delete_me = 1;
+                        win32_handlers_delete_me = 1;
+                     }
+                   wh->references--;
+                }
+
+             if (win32_handler_current) /* may have changed in recursive main loops */
+               win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
+          }
+        res = 1;
+     }
+   else
+     {
+        ERR("unknown result...\n");
+        res = -1;
+     }
+
+   /* Remove event objects again */
+   for(i = 0; i < events_nbr; i++)
+     WSACloseEvent(objects[i]);
+
+   return res;
+}
+#endif
diff --git a/src/lib/ecore/ecore_pipe.c b/src/lib/ecore/ecore_pipe.c
new file mode 100644 (file)
index 0000000..0eea8ce
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+/* How of then we should retry to write to the pipe */
+#define ECORE_PIPE_WRITE_RETRY 6
+
+/*
+ * On Windows, pipe() is implemented with sockets.
+ * Contrary to Linux, Windows uses different functions
+ * for sockets and fd's: write() is for fd's and send
+ * is for sockets. So I need to put some win32 code
+ * here. I can't think of a solution where the win32
+ * code is in Evil and not here.
+ */
+
+#ifdef _WIN32
+
+# include <winsock2.h>
+
+# define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
+# define pipe_read(fd, buffer, size)  recv((fd), (char *)(buffer), size, 0)
+# define pipe_close(fd)               closesocket(fd)
+# define PIPE_FD_INVALID              INVALID_SOCKET
+# define PIPE_FD_ERROR                SOCKET_ERROR
+
+#else
+
+# include <unistd.h>
+# include <fcntl.h>
+
+# define pipe_write(fd, buffer, size) write((fd), buffer, size)
+# define pipe_read(fd, buffer, size)  read((fd), buffer, size)
+# define pipe_close(fd)               close(fd)
+# define PIPE_FD_INVALID              -1
+# define PIPE_FD_ERROR                -1
+
+#endif /* ! _WIN32 */
+
+struct _Ecore_Pipe
+{
+   ECORE_MAGIC;
+   int               fd_read;
+   int               fd_write;
+   Ecore_Fd_Handler *fd_handler;
+   const void       *data;
+   void            (*handler) (void *data, void *buffer, unsigned int nbyte);
+   unsigned int      len;
+   size_t            already_read;
+   void             *passed_data;
+};
+
+
+static int _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler);
+
+/**
+ * @defgroup Ecore_Pipe_Group Pipe wrapper
+ *
+ * These functions wrap the pipe / write / read functions to
+ * easily integrate a loop that is in its own thread to the ecore
+ * main loop.
+ *
+ * The ecore_pipe_add() function creates file descriptors (sockets on
+ * Windows) and attach an handle to the ecore main loop. That handle is
+ * called when data is read in the pipe. To write data in the pipe,
+ * just call ecore_pipe_write(). When you are done, just call
+ * ecore_pipe_del().
+ *
+ * Here is an example that uses the pipe wrapper with a Gstreamer
+ * pipeline. For each decoded frame in the Gstreamer thread, a handle
+ * is called in the ecore thread.
+ *
+ * @code#include <gst/gst.h>
+ * #include <Ecore.h>
+ *
+ * static int nbr = 0;
+ *
+ * static GstElement *_buid_pipeline (gchar *filename, Ecore_Pipe *pipe);
+ *
+ * static void new_decoded_pad_cb (GstElement *demuxer,
+ *                                 GstPad     *new_pad,
+ *                                 gpointer    user_data);
+ *
+ * static void handler(void *data, void *buf, unsigned int len)
+ * {
+ *   GstBuffer  *buffer = *((GstBuffer **)buf);
+ *
+ *   printf ("handler : %p\n", buffer);
+ *   printf ("frame  : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(buffer), buffer);
+ *   gst_buffer_unref (buffer);
+ * }
+ *
+ *
+ * static void handoff (GstElement* object,
+ *                      GstBuffer* arg0,
+ *                      GstPad* arg1,
+ *                      gpointer user_data)
+ * {
+ *   Ecore_Pipe *pipe;
+ *
+ *   pipe = (Ecore_Pipe *)user_data;
+ *   printf ("handoff : %p\n", arg0);
+ *   gst_buffer_ref (arg0);
+ *   ecore_pipe_write(pipe, &arg0, sizeof(arg0));
+ * }
+ *
+ * int
+ * main (int argc, char *argv[])
+ * {
+ *   GstElement *pipeline;
+ *   char *filename;
+ *   Ecore_Pipe *pipe;
+ *
+ *   gst_init (&argc, &argv);
+ *
+ *   if (!ecore_init ())
+ *     {
+ *       gst_deinit ();
+ *       return 0;
+ *     }
+ *
+ *   pipe = ecore_pipe_add (handler);
+ *   if (!pipe)
+ *     {
+ *       ecore_shutdown ();
+ *       gst_deinit ();
+ *       return 0;
+ *     }
+ *
+ *   if (argc < 2) {
+ *     g_print ("usage: %s file.avi\n", argv[0]);
+ *     ecore_pipe_del (pipe);
+ *     ecore_shutdown ();
+ *     gst_deinit ();
+ *     return 0;
+ *   }
+ *   filename = argv[1];
+ *
+ *   pipeline = _buid_pipeline (filename, pipe);
+ *   if (!pipeline) {
+ *     g_print ("Error during the pipeline building\n");
+ *     ecore_pipe_del (pipe);
+ *     ecore_shutdown ();
+ *     gst_deinit ();
+ *     return -1;
+ *   }
+ *
+ *   gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ *
+ *   ecore_main_loop_begin();
+ *
+ *   ecore_pipe_del (pipe);
+ *   ecore_shutdown ();
+ *   gst_deinit ();
+ *
+ *   return 0;
+ * }
+ *
+ * static void
+ * new_decoded_pad_cb (GstElement *demuxer,
+ *                     GstPad     *new_pad,
+ *                     gpointer    user_data)
+ * {
+ *   GstElement *decoder;
+ *   GstPad *pad;
+ *   GstCaps *caps;
+ *   gchar *str;
+ *
+ *   caps = gst_pad_get_caps (new_pad);
+ *   str = gst_caps_to_string (caps);
+ *
+ *   if (g_str_has_prefix (str, "video/")) {
+ *     decoder = GST_ELEMENT (user_data);
+ *
+ *     pad = gst_element_get_pad (decoder, "sink");
+ *     if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, pad))) {
+ *       g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad),
+ *                  GST_DEBUG_PAD_NAME (pad));
+ *     }
+ *   }
+ *   g_free (str);
+ *   gst_caps_unref (caps);
+ * }
+ *
+ * static GstElement *
+ * _buid_pipeline (gchar *filename, Ecore_Pipe *pipe)
+ * {
+ *   GstElement          *pipeline;
+ *   GstElement          *filesrc;
+ *   GstElement          *demuxer;
+ *   GstElement          *decoder;
+ *   GstElement          *sink;
+  GstStateChangeReturn res;
+ *
+ *   pipeline = gst_pipeline_new ("pipeline");
+ *   if (!pipeline)
+ *     return NULL;
+ *
+ *   filesrc = gst_element_factory_make ("filesrc", "filesrc");
+ *   if (!filesrc) {
+ *     printf ("no filesrc");
+ *     goto failure;
+ *   }
+ *   g_object_set (G_OBJECT (filesrc), "location", filename, NULL);
+ *
+ *   demuxer = gst_element_factory_make ("oggdemux", "demuxer");
+ *   if (!demuxer) {
+ *     printf ("no demux");
+ *     goto failure;
+ *   }
+ *
+ *   decoder = gst_element_factory_make ("theoradec", "decoder");
+ *   if (!decoder) {
+ *     printf ("no dec");
+ *     goto failure;
+ *   }
+ *
+ *   g_signal_connect (demuxer, "pad-added",
+ *                     G_CALLBACK (new_decoded_pad_cb), decoder);
+ *
+ *   sink = gst_element_factory_make ("fakesink", "sink");
+ *   if (!sink) {
+ *     printf ("no sink");
+ *     goto failure;
+ *   }
+ *   g_object_set (G_OBJECT (sink), "sync", EINA_TRUE, NULL);
+ *   g_object_set (G_OBJECT (sink), "signal-handoffs", EINA_TRUE, NULL);
+ *   g_signal_connect (sink, "handoff",
+ *                     G_CALLBACK (handoff), pipe);
+ *
+ *   gst_bin_add_many (GST_BIN (pipeline),
+ *                     filesrc, demuxer, decoder, sink, NULL);
+ *
+ *   if (!gst_element_link (filesrc, demuxer))
+ *     goto failure;
+ *   if (!gst_element_link (decoder, sink))
+ *     goto failure;
+ *
+ *   res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ *   if (res == GST_STATE_CHANGE_FAILURE)
+ *     goto failure;
+ *
+ *   res = gst_element_get_state( pipeline, NULL, NULL, GST_CLOCK_TIME_NONE );
+ *   if (res != GST_STATE_CHANGE_SUCCESS)
+ *     goto failure;
+ *
+ *   return pipeline;
+ *
+ *  failure:
+ *   gst_object_unref (GST_OBJECT (pipeline));
+ *   return NULL;
+ * }
+ * @endcode
+ */
+
+
+/**
+ * Create two file descriptors (sockets on Windows). Add
+ * a callback that will be called when the file descriptor that
+ * is listened receives data. An event is also put in the event
+ * queue when data is received.
+ *
+ * @param handler The handler called when data is received.
+ * @param data    Data to pass to @p handler when it is called.
+ * @return        A newly created Ecore_Pipe object if successful.
+ *                @c NULL otherwise.
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI Ecore_Pipe *
+ecore_pipe_add(void (*handler) (void *data, void *buffer, unsigned int nbyte),
+               const void *data)
+{
+   Ecore_Pipe *p;
+   int         fds[2];
+
+   if (!handler) return NULL;
+
+   p = (Ecore_Pipe *)calloc(1, sizeof(Ecore_Pipe));
+   if (!p) return NULL;
+
+   if (pipe(fds))
+     {
+        free(p);
+        return NULL;
+     }
+
+   ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE);
+   p->fd_read = fds[0];
+   p->fd_write = fds[1];
+   p->handler = handler;
+   p->data = data;
+
+   fcntl(p->fd_read, F_SETFL, O_NONBLOCK);
+   p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
+                                          ECORE_FD_READ,
+                                          _ecore_pipe_read,
+                                          p,
+                                          NULL, NULL);
+   return p;
+}
+
+/**
+ * Free an Ecore_Pipe object created with ecore_pipe_add().
+ *
+ * @param p The Ecore_Pipe object to be freed.
+ * @return The pointer to the private data
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI void *
+ecore_pipe_del(Ecore_Pipe *p)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_del");
+       return NULL;
+     }
+   if (p->fd_handler != NULL) ecore_main_fd_handler_del(p->fd_handler);
+   if (p->fd_read != PIPE_FD_INVALID) pipe_close(p->fd_read);
+   if (p->fd_write != PIPE_FD_INVALID) pipe_close(p->fd_write);
+   data = (void *)p->data;
+   free(p);
+   return data;
+}
+
+/**
+ * Close the read end of an Ecore_Pipe object created with ecore_pipe_add().
+ *
+ * @param p The Ecore_Pipe object.
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI void
+ecore_pipe_read_close(Ecore_Pipe *p)
+{
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_close");
+       return;
+     }
+   ecore_main_fd_handler_del(p->fd_handler);
+   p->fd_handler = NULL;
+   pipe_close(p->fd_read);
+   p->fd_read = PIPE_FD_INVALID;
+}
+
+/**
+ * Close the write end of an Ecore_Pipe object created with ecore_pipe_add().
+ *
+ * @param p The Ecore_Pipe object.
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI void
+ecore_pipe_write_close(Ecore_Pipe *p)
+{
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write_close");
+       return;
+     }
+   pipe_close(p->fd_write);
+   p->fd_write = PIPE_FD_INVALID;
+}
+
+/**
+ * Write on the file descriptor the data passed as parameter.
+ *
+ * @param p      The Ecore_Pipe object.
+ * @param buffer The data to write into the pipe.
+ * @param nbytes The size of the @p buffer in bytes
+ * @return       Returns EINA_TRUE on a successful write, EINA_FALSE on an error
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI int
+ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes)
+{
+   ssize_t ret;
+   size_t  already_written = 0;
+   int     retry = ECORE_PIPE_WRITE_RETRY;
+
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write");
+       return EINA_FALSE;
+     }
+
+   if (p->fd_write == PIPE_FD_INVALID) return EINA_FALSE;
+
+   /* First write the len into the pipe */
+   do
+     {
+       ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes));
+       if (ret == sizeof(nbytes))
+         {
+            retry = ECORE_PIPE_WRITE_RETRY;
+            break;
+         }
+       else if (ret > 0)
+         {
+            /* XXX What should we do here? */
+            ERR("The length of the data was not written complete"
+                " to the pipe");
+            return EINA_FALSE;
+         }
+       else if (ret == PIPE_FD_ERROR && errno == EPIPE)
+         {
+            pipe_close(p->fd_write);
+            p->fd_write = PIPE_FD_INVALID;
+            return EINA_FALSE;
+         }
+       else if (ret == PIPE_FD_ERROR && errno == EINTR)
+         /* try it again */
+         ;
+       else
+         {
+            ERR("An unhandled error (ret: %zd errno: %d)"
+                "occured while writing to the pipe the length",
+                ret, errno);
+         }
+     }
+   while (retry--);
+
+   if (retry != ECORE_PIPE_WRITE_RETRY) return EINA_FALSE;
+
+   /* and now pass the data to the pipe */
+   do
+     {
+       ret = pipe_write(p->fd_write,
+                         ((unsigned char *)buffer) + already_written,
+                         nbytes - already_written);
+        
+       if (ret == (ssize_t)(nbytes - already_written))
+         return EINA_TRUE;
+       else if (ret >= 0)
+         {
+            already_written -= ret;
+            continue;
+         }
+       else if (ret == PIPE_FD_ERROR && errno == EPIPE)
+         {
+            pipe_close(p->fd_write);
+            p->fd_write = PIPE_FD_INVALID;
+            return EINA_FALSE;
+         }
+       else if (ret == PIPE_FD_ERROR && errno == EINTR)
+         /* try it again */
+         ;
+       else
+         {
+            ERR("An unhandled error (ret: %zd errno: %d)"
+                "occured while writing to the pipe the length",
+                ret, errno);
+         }
+     }
+   while (retry--);
+
+   return EINA_FALSE;
+}
+
+/* Private function */
+
+static int
+_ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Ecore_Pipe  *p;
+   double       start_time;
+
+   p = (Ecore_Pipe *)data;
+   start_time = ecore_time_get();
+
+   do
+     {
+       ssize_t       ret;
+
+       /* if we already have read some data we don't need to read the len
+        * but to finish the already started job
+        */
+       if (p->len == 0)
+         {
+            /* read the len of the passed data */
+            ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));
+
+            /* catch the non error case first */
+            if (ret == sizeof(p->len))
+              ;
+            else if (ret > 0)
+              {
+                 /* XXX What should we do here? */
+                 ERR("Only read %zd bytes from the pipe, although"
+                     " we need to read %zd bytes.", ret, sizeof(p->len));
+              }
+            else if (ret == 0)
+              {
+                 p->handler((void *)p->data, NULL, 0);
+                 pipe_close(p->fd_read);
+                 p->fd_read = PIPE_FD_INVALID;
+                 p->fd_handler = NULL;
+                 return ECORE_CALLBACK_CANCEL;
+              }
+#ifndef _WIN32
+            else if ((ret == PIPE_FD_ERROR) && ((errno == EINTR) || (errno == EAGAIN)))
+              return ECORE_CALLBACK_RENEW;
+            else
+              {
+                 ERR("An unhandled error (ret: %zd errno: %d)"
+                     "occured while reading from the pipe the length",
+                     ret, errno);
+                  return ECORE_CALLBACK_RENEW;
+              }
+#else
+            else /* ret == PIPE_FD_ERROR is the only other case on Windows */
+              {
+                  if (WSAGetLastError() != WSAEWOULDBLOCK)
+                    {
+                       p->handler((void *)p->data, NULL, 0);
+                       pipe_close(p->fd_read);
+                       p->fd_read = PIPE_FD_INVALID;
+                       p->fd_handler = NULL;
+                       return ECORE_CALLBACK_CANCEL;
+                    }
+              }
+#endif
+         }
+
+       if (!p->passed_data)
+         p->passed_data = malloc(p->len);
+
+       /* and read the passed data */
+       ret = pipe_read(p->fd_read,
+                        ((unsigned char *)p->passed_data) + p->already_read,
+                        p->len - p->already_read);
+        
+       /* catch the non error case first */
+       if (ret == (ssize_t)(p->len - p->already_read))
+         {
+            p->handler((void *)p->data, p->passed_data, p->len);
+            free(p->passed_data);
+            /* reset all values to 0 */
+            p->passed_data = NULL;
+            p->already_read = 0;
+            p->len = 0;
+         }
+       else if (ret >= 0)
+         {
+            p->already_read += ret;
+            return ECORE_CALLBACK_RENEW;
+         }
+       else if (ret == 0)
+         {
+            p->handler((void *)p->data, NULL, 0);
+            pipe_close(p->fd_read);
+            p->fd_read = PIPE_FD_INVALID;
+            p->fd_handler = NULL;
+            return ECORE_CALLBACK_CANCEL;
+         }
+#ifndef _WIN32
+       else if (ret == PIPE_FD_ERROR && (errno == EINTR || errno == EAGAIN))
+         return ECORE_CALLBACK_RENEW;
+       else
+         {
+            ERR("An unhandled error (ret: %zd errno: %d)"
+                "occured while reading from the pipe the data",
+                ret, errno);
+            return ECORE_CALLBACK_RENEW;
+         }
+#else
+        else /* ret == PIPE_FD_ERROR is the only other case on Windows */
+          {
+             if (WSAGetLastError() != WSAEWOULDBLOCK)
+               {
+                  p->handler((void *)p->data, NULL, 0);
+                  pipe_close(p->fd_read);
+                  p->fd_read = PIPE_FD_INVALID;
+                  p->fd_handler = NULL;
+                  return ECORE_CALLBACK_CANCEL;
+               }
+             else
+               break;
+          }
+#endif
+     }
+   while (ecore_time_get() - start_time < ecore_animator_frametime_get());
+   
+   return ECORE_CALLBACK_RENEW;
+}
diff --git a/src/lib/ecore/ecore_poll.c b/src/lib/ecore/ecore_poll.c
new file mode 100644 (file)
index 0000000..09ae899
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Poller
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   int           ibit;
+   unsigned char delete_me : 1;
+   int           (*func) (void *data);
+   void          *data;
+};
+
+
+static Ecore_Timer    *timer = NULL;
+static int             min_interval = -1;
+static int             interval_incr = 0;
+static int             at_tick = 0;
+static int             just_added_poller = 0;
+static int             poller_delete_count = 0;
+static int             poller_walking = 0;
+static double          poll_interval = 0.125;
+static double          poll_cur_interval = 0.0;
+static double          last_tick = 0.0;
+static Ecore_Poller   *pollers[16] =
+{
+   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+};
+static unsigned short  poller_counters[16] =
+{
+   0,0,0,0,0,0,0,0,
+   0,0,0,0,0,0,0,0
+};
+
+static void _ecore_poller_next_tick_eval(void);
+static int _ecore_poller_cb_timer(void *data);
+
+static void
+_ecore_poller_next_tick_eval(void)
+{
+   int i;
+   double interval;
+
+   min_interval = -1;
+   for (i = 0; i < 15; i++)
+     {
+       if (pollers[i])
+         {
+            min_interval = i;
+            break;
+         }
+     }
+   if (min_interval < 0)
+     {
+       /* no pollers */
+       if (timer)
+         {
+            ecore_timer_del(timer);
+            timer = NULL;
+         }
+       return;
+     }
+   interval_incr = (1 << min_interval);
+   interval = interval_incr * poll_interval;
+   /* we are at the tick callback - so no need to do inter-tick adjustments
+    * so we can fasttrack this as t -= last_tick in theory is 0.0 (though
+    * in practice it will be a very very very small value. also the tick
+    * callback will adjust the timer interval at the end anyway */
+   if (at_tick)
+     {
+       if (!timer)
+         timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
+     }
+   else
+     {
+       double t;
+
+       if (!timer)
+         timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
+       else
+         {
+            t = ecore_time_get();
+            if (interval != poll_cur_interval)
+              {
+                 t -= last_tick; /* time since we last ticked */
+                 /* delete the timer and reset it to tick off in the new
+                  * time interval. at the tick this will be adjusted */
+                 ecore_timer_del(timer);
+                 timer = ecore_timer_add(interval - t,
+                                         _ecore_poller_cb_timer, NULL);
+              }
+         }
+     }
+   poll_cur_interval = interval;
+}
+
+static int
+_ecore_poller_cb_timer(void *data __UNUSED__)
+{
+   int i;
+   Ecore_Poller *poller, *l;
+   int changes = 0;
+
+   at_tick++;
+   last_tick = ecore_time_get();
+   /* we have 16 counters - each incriments every time the poller counter
+    * "ticks". it incriments by the minimum interval (which can be 1, 2, 4,
+    * 7, 16 etc. up to 32768) */
+   for (i = 0; i < 15; i++)
+     {
+       poller_counters[i] += interval_incr;
+       /* wrap back to 0 if we exceed out loop count for the counter */
+       if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
+     }
+
+   just_added_poller = 0;
+   /* walk the pollers now */
+   poller_walking++;
+   for (i = 0; i < 15; i++)
+     {
+       /* if the counter is @ 0 - this means that counter "went off" this
+        * tick interval, so run all pollers hooked to that counter */
+       if (poller_counters[i] == 0)
+         {
+            EINA_INLIST_FOREACH(pollers[i], poller)
+              {
+                 if (!poller->delete_me)
+                   {
+                      if (!poller->func(poller->data))
+                        {
+                           if (!poller->delete_me)
+                             {
+                                poller->delete_me = 1;
+                                poller_delete_count++;
+                             }
+                        }
+                   }
+              }
+         }
+     }
+   poller_walking--;
+
+   /* handle deletes afterwards */
+   if (poller_delete_count > 0)
+     {
+       /* FIXME: walk all pollers and remove deleted ones */
+       for (i = 0; i < 15; i++)
+         {
+             for (l = pollers[i]; l;)
+              {
+                  poller = l;
+                 l = (Ecore_Poller *) EINA_INLIST_GET(l)->next;
+                 if (poller->delete_me)
+                   {
+                      pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(poller));
+                      free(poller);
+                      poller_delete_count--;
+                      changes++;
+                      if (poller_delete_count <= 0) break;
+                   }
+              }
+            if (poller_delete_count <= 0) break;
+         }
+     }
+   /* if we deleted or added any pollers, then we need to re-evaluate our
+    * minimum poll interval */
+   if ((changes > 0) || (just_added_poller > 0))
+     _ecore_poller_next_tick_eval();
+
+   just_added_poller = 0;
+   poller_delete_count = 0;
+
+   at_tick--;
+
+   /* if the timer was deleted then there is no point returning 1 - ambiguous
+    * if we do as it im plies "keep running me" but we have been deleted
+    * anyway */
+   if (!timer) return 0;
+
+   /* adjust interval */
+   ecore_timer_interval_set(timer, poll_cur_interval);
+   return 1;
+}
+
+/**
+ * @defgroup Ecore_Poll_Group Ecore Poll Functions
+ *
+ * These functions are for the need to poll information, but provide a shared
+ * abstracted API to pool such polling to minimise wakeup and ensure all the
+ * polling happens in as few spots as possible areound a core poll interval.
+ * For now only 1 core poller type is supprted: ECORE_POLLER_CORE
+ */
+
+
+/**
+ * Sets the time between ticks (in seconds) for the given ticker clock.
+ * @param   type The ticker type to adjust
+ * @param   poll_time The time (in seconds) between ticks of the clock
+ * @ingroup Ecore_Poller_Group
+ *
+ * This will adjust the time between ticks of the given ticker type defined
+ * by @p type to the time period defined by @p poll_time.
+ */
+EAPI void
+ecore_poller_poll_interval_set(Ecore_Poller_Type type __UNUSED__, double poll_time)
+{
+   poll_interval = poll_time;
+   _ecore_poller_next_tick_eval();
+}
+
+/**
+ * Gets the time between ticks (in seconds) for the given ticker clock.
+ * @param   type The ticker type to query
+ * @return  The time in seconds between ticks of the ticker clock
+ * @ingroup Ecore_Poller_Group
+ *
+ * This will get the time between ticks of the specifider ticker clock.
+ */
+EAPI double
+ecore_poller_poll_interval_get(Ecore_Poller_Type type __UNUSED__)
+{
+   return poll_interval;
+}
+
+/**
+ * Creates a poller to call the given function at a particular tick interval.
+ * @param   type The ticker type to attach the poller to
+ * @param   interval The poll interval
+ * @param   func The given function.  If @p func returns 1, the poller is
+ *               rescheduled for the next tick interval.
+ * @param   data Data to pass to @p func when it is called.
+ * @return  A poller object on success.  @c NULL on failure.
+ * @ingroup Ecore_Poller_Group
+ *
+ * This function adds a poller callback that is to be called regularly
+ * along with all other poller callbacks so the pollers are synchronized with
+ * all other pollers running off the same poller type and at the same tick
+ * interval. This should be used for polling things when polling is desired
+ * or required, and you do not have specific requirements on the exact times
+ * to poll and want to avoid extra process wakeups for polling. This will
+ * save power as the CPU has more of a chance to go into a low power state
+ * the longer it is asleep for, so this should be used if you are at all
+ * power conscious.
+ *
+ * The @p type parameter defines the poller tick type (there is a virtual
+ * clock ticking all the time - though ecore avoids making it tick when
+ * there will not be any work to do at that tick point). There is only one
+ * ticker at the moment - that is ECORE_POLLER_CORE. This is here for future
+ * expansion if multiple clocks with different frequencies are really required.
+ * The default time between ticks for the ECORE_POLLER_CORE ticker is 0.125
+ * seconds.
+ *
+ * The @p interval is the number of ticker ticks that will pass by in between
+ * invocations of the @p func callback. This must be between 1 and 32768
+ * inclusive, and must be a power of 2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768).
+ * If it is 1, then the function will be called every tick. if it is 2, then it
+ * will be called every 2nd tick, if it is 8, then every 8th tick etc. Exactly
+ * which tick is undefined, as only the interval between calls can be defined.
+ * Ecore will endeavour to keep pollers synchronised and to call as many in
+ * 1 wakeup event as possible.
+ *
+ * This function adds a poller and returns its handle on success and NULL on
+ * failure. The function @p func will be called at tick intervals described
+ * above. The function will be passed the @p data pointer as its parameter.
+ *
+ * When the poller @p func is called, it must return a value of either
+ * 1 (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL). If it
+ * returns 1, it will be called again at the next tick, or if it returns
+ * 0 it will be deleted automatically making any references/handles for it
+ * invalid.
+ */
+EAPI Ecore_Poller *
+ecore_poller_add(Ecore_Poller_Type type __UNUSED__, int interval, int (*func) (void *data), const void *data)
+{
+   Ecore_Poller *poller;
+   int ibit;
+
+   if (!func) return NULL;
+   if (interval < 1) interval = 1;
+
+   poller = calloc(1, sizeof(Ecore_Poller));
+   if (!poller) return NULL;
+   ECORE_MAGIC_SET(poller, ECORE_MAGIC_POLLER);
+   /* interval MUST be a power of 2, so enforce it */
+   if (interval < 1) interval = 1;
+   ibit = -1;
+   while (interval != 0)
+     {
+       ibit++;
+       interval >>= 1;
+     }
+   /* only allow up to 32768 - i.e. ibit == 15, so limit it */
+   if (ibit > 15) ibit = 15;
+
+   poller->ibit = ibit;
+   poller->func = func;
+   poller->data = (void *)data;
+   pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
+   if (poller_walking)
+     just_added_poller++;
+   else
+     _ecore_poller_next_tick_eval();
+   return poller;
+}
+
+/**
+ * Delete the specified poller from the timer list.
+ * @param   poller The poller to delete.
+ * @return  The data pointer set for the timer when @ref ecore_poller_add was
+ *          called.  @c NULL is returned if the function is unsuccessful.
+ * @ingroup Ecore_Poller_Group
+ *
+ * Note: @p poller must be a valid handle. If the poller function has already
+ * returned 0, the handle is no longer valid (and does not need to be delete).
+ */
+EAPI void *
+ecore_poller_del(Ecore_Poller *poller)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
+     {
+       ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
+                        "ecore_poller_del");
+       return NULL;
+     }
+   /* we are walking the poller list - a bad idea to remove from it while
+    * walking it, so just flag it as delete_me and come back to it after
+    * the loop has finished */
+   if (poller_walking > 0)
+     {
+       poller_delete_count++;
+       poller->delete_me = 1;
+       return poller->data;
+     }
+   /* not in loop so safe - delete immediately */
+   data = poller->data;
+   pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
+   free(poller);
+   _ecore_poller_next_tick_eval();
+   return data;
+}
+
+void
+_ecore_poller_shutdown(void)
+{
+   int i;
+   Ecore_Poller *poller;
+
+   for (i = 0; i < 15; i++)
+     {
+       while ((poller = pollers[i]))
+         {
+            pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(pollers[i]));
+            free(poller);
+         }
+     }
+}
diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h
new file mode 100644 (file)
index 0000000..ea59794
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef _ECORE_PRIVATE_H
+#define _ECORE_PRIVATE_H
+
+extern int _ecore_log_dom ;
+#ifdef  _ECORE_DEFAULT_LOG_DOM
+# undef _ECORE_DEFAULT_LOG_DOM
+#endif
+#define _ECORE_DEFAULT_LOG_DOM _ecore_log_dom
+
+#ifdef ECORE_DEFAULT_LOG_COLOR
+# undef ECORE_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ECORE_DEFAULT_LOG_DOM, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ECORE_DEFAULT_LOG_DOM, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ECORE_DEFAULT_LOG_DOM, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ECORE_DEFAULT_LOG_DOM, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ECORE_DEFAULT_LOG_DOM, __VA_ARGS__)
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+#ifndef MIN
+# define MIN(x, y) (((x) > (y)) ? (y) : (x))
+#endif
+
+#ifndef MAX
+# define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef ABS
+# define ABS(x) ((x) < 0 ? -(x) : (x))
+#endif
+
+#ifndef CLAMP
+# define CLAMP(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
+#endif
+
+#define READBUFSIZ 65536
+
+#define ECORE_MAGIC_NONE            0x1234fedc
+#define ECORE_MAGIC_EXE             0xf7e812f5
+#define ECORE_MAGIC_TIMER           0xf7d713f4
+#define ECORE_MAGIC_IDLER           0xf7c614f3
+#define ECORE_MAGIC_IDLE_ENTERER    0xf7b515f2
+#define ECORE_MAGIC_IDLE_EXITER     0xf7601afd
+#define ECORE_MAGIC_FD_HANDLER      0xf7a416f1
+#define ECORE_MAGIC_EVENT_HANDLER   0xf79317f0
+#define ECORE_MAGIC_EVENT_FILTER    0xf78218ff
+#define ECORE_MAGIC_EVENT           0xf77119fe
+#define ECORE_MAGIC_ANIMATOR        0xf7643ea5
+#define ECORE_MAGIC_POLLER          0xf7568127
+#define ECORE_MAGIC_PIPE            0xf7458226
+#define ECORE_MAGIC_WIN32_HANDLER   0xf7e8f1a3
+#define ECORE_MAGIC_JOB             0x76543210
+
+
+#define ECORE_MAGIC                 Ecore_Magic  __magic
+
+#define ECORE_MAGIC_SET(d, m)       (d)->__magic = (m)
+#define ECORE_MAGIC_CHECK(d, m)     ((d) && ((d)->__magic == (m)))
+#define ECORE_MAGIC_FAIL(d, m, fn)  _ecore_magic_fail((d), (d) ? (d)->__magic : 0, (m), (fn));
+
+/* undef the following, we want our version */
+#undef FREE
+#define FREE(ptr) free(ptr); ptr = NULL;
+
+#undef IF_FREE
+#define IF_FREE(ptr) if (ptr) free(ptr); ptr = NULL;
+
+#undef IF_FN_DEL
+#define IF_FN_DEL(_fn, ptr) if (ptr) { _fn(ptr); ptr = NULL; }
+
+EAPI void ecore_print_warning(const char *function, const char *sparam);
+
+/* convenience macros for checking pointer parameters for non-NULL */
+#undef CHECK_PARAM_POINTER_RETURN
+#define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \
+     if (!(param)) \
+        { \
+           ecore_print_warning(__FUNCTION__, sparam); \
+           return ret; \
+        }
+
+#undef CHECK_PARAM_POINTER
+#define CHECK_PARAM_POINTER(sparam, param) \
+     if (!(param)) \
+        { \
+           ecore_print_warning(__FUNCTION__, sparam); \
+           return; \
+        }
+
+typedef unsigned int              Ecore_Magic;
+
+EAPI void          _ecore_magic_fail(const void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname);
+
+void          _ecore_timer_shutdown(void);
+void          _ecore_timer_cleanup(void);
+void          _ecore_timer_enable_new(void);
+double        _ecore_timer_next_get(void);
+int           _ecore_timers_exists(void);
+int           _ecore_timer_call(double when);
+
+void          _ecore_idler_shutdown(void);
+int           _ecore_idler_call(void);
+int           _ecore_idler_exist(void);
+
+void          _ecore_idle_enterer_shutdown(void);
+void          _ecore_idle_enterer_call(void);
+int           _ecore_idle_enterer_exist(void);
+
+void          _ecore_idle_exiter_shutdown(void);
+void          _ecore_idle_exiter_call(void);
+int           _ecore_idle_exiter_exist(void);
+
+void          _ecore_event_shutdown(void);
+int           _ecore_event_exist(void);
+Ecore_Event  *_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data);
+void          _ecore_event_call(void);
+
+Ecore_Timer  *_ecore_exe_doomsday_clock_get(Ecore_Exe *exe);
+void          _ecore_exe_doomsday_clock_set(Ecore_Exe *exe, Ecore_Timer *dc);
+
+EAPI void    *_ecore_event_signal_user_new(void);
+void         *_ecore_event_signal_hup_new(void);
+void         *_ecore_event_signal_exit_new(void);
+void         *_ecore_event_signal_power_new(void);
+void         *_ecore_event_signal_realtime_new(void);
+
+void          _ecore_main_shutdown(void);
+
+#ifdef _WIN32
+static inline void _ecore_signal_shutdown(void) { }
+static inline void _ecore_signal_init(void) { }
+static inline int  _ecore_signal_count_get(void) { return 0; }
+static inline void _ecore_signal_call(void) { }
+#else
+void          _ecore_signal_shutdown(void);
+void          _ecore_signal_init(void);
+int           _ecore_signal_count_get(void);
+void          _ecore_signal_call(void);
+#endif
+
+void          _ecore_exe_init(void);
+void          _ecore_exe_shutdown(void);
+#ifndef _WIN32
+Ecore_Exe    *_ecore_exe_find(pid_t pid);
+void         *_ecore_exe_event_del_new(void);
+void          _ecore_exe_event_del_free(void *data, void *ev);
+#endif
+
+void          _ecore_animator_shutdown(void);
+
+void          _ecore_poller_shutdown(void);
+
+EAPI void         *_ecore_list2_append           (void *in_list, void *in_item);
+EAPI void         *_ecore_list2_prepend          (void *in_list, void *in_item);
+EAPI void         *_ecore_list2_append_relative  (void *in_list, void *in_item, void *in_relative);
+EAPI void         *_ecore_list2_prepend_relative (void *in_list, void *in_item, void *in_relative);
+EAPI void         *_ecore_list2_remove           (void *in_list, void *in_item);
+EAPI void         *_ecore_list2_find             (void *in_list, void *in_item);
+
+void          _ecore_fps_debug_init(void);
+void          _ecore_fps_debug_shutdown(void);
+void          _ecore_fps_debug_runtime_add(double t);
+
+void _ecore_thread_init(void);
+void _ecore_thread_shutdown(void);
+
+void _ecore_glib_init(void);
+void _ecore_glib_shutdown(void);
+
+void _ecore_job_init(void);
+void _ecore_job_shutdown(void);
+
+extern int    _ecore_fps_debug;
+extern double _ecore_loop_time;
+extern Eina_Bool _ecore_glib_always_integrate;
+
+#endif
diff --git a/src/lib/ecore/ecore_signal.c b/src/lib/ecore/ecore_signal.c
new file mode 100644 (file)
index 0000000..5d0ddb5
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+/* make mono happy - this is evil though... */
+#undef SIGPWR
+/* valgrind in some versions/setups uses SIGRT's... hmmm */
+#undef SIGRTMIN
+
+typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
+
+static void _ecore_signal_callback_set(int sig, Signal_Handler func);
+static void _ecore_signal_callback_ignore(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigchld(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigusr1(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigusr2(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sighup(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigquit(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigint(int sig, siginfo_t *si, void *foo);
+static void _ecore_signal_callback_sigterm(int sig, siginfo_t *si, void *foo);
+#ifdef SIGPWR
+static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
+#endif
+
+#ifdef SIGRTMIN
+static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
+#endif
+
+static int _ecore_signal_exe_exit_delay(void *data);
+
+//#define MAXSIGQ 256 // 32k
+#define MAXSIGQ 64 // 8k
+
+static volatile sig_atomic_t sig_count = 0;
+static volatile sig_atomic_t sigchld_count = 0;
+static volatile sig_atomic_t sigusr1_count = 0;
+static volatile sig_atomic_t sigusr2_count = 0;
+static volatile sig_atomic_t sighup_count = 0;
+static volatile sig_atomic_t sigquit_count = 0;
+static volatile sig_atomic_t sigint_count = 0;
+static volatile sig_atomic_t sigterm_count = 0;
+#ifdef SIGPWR
+static volatile sig_atomic_t sigpwr_count = 0;
+#endif
+#ifdef SIGRTMIN
+static volatile sig_atomic_t *sigrt_count = NULL;
+#endif
+
+static volatile siginfo_t sigchld_info[MAXSIGQ];
+static volatile siginfo_t sigusr1_info[MAXSIGQ];
+static volatile siginfo_t sigusr2_info[MAXSIGQ];
+static volatile siginfo_t sighup_info[MAXSIGQ];
+static volatile siginfo_t sigquit_info[MAXSIGQ];
+static volatile siginfo_t sigint_info[MAXSIGQ];
+static volatile siginfo_t sigterm_info[MAXSIGQ];
+#ifdef SIGPWR
+static volatile siginfo_t sigpwr_info[MAXSIGQ];
+#endif
+#ifdef SIGRTMIN
+static volatile siginfo_t *sigrt_info[MAXSIGQ];
+#endif
+
+void
+_ecore_signal_shutdown(void)
+{
+#ifdef SIGRTMIN
+   int i, num = SIGRTMAX - SIGRTMIN;
+#endif
+
+   _ecore_signal_callback_set(SIGPIPE, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGALRM, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGCHLD, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGUSR1, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGUSR2, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGHUP,  (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGQUIT, (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGINT,  (Signal_Handler) SIG_DFL);
+   _ecore_signal_callback_set(SIGTERM, (Signal_Handler) SIG_DFL);
+#ifdef SIGPWR
+   _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL);
+   sigpwr_count = 0;
+#endif
+   sigchld_count = 0;
+   sigusr1_count = 0;
+   sigusr2_count = 0;
+   sighup_count = 0;
+   sigquit_count = 0;
+   sigint_count = 0;
+   sigterm_count = 0;
+   sig_count = 0;
+
+#ifdef SIGRTMIN
+   for (i = 0; i < num; i++)
+     {
+       _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL);
+       sigrt_count[i] = 0;
+     }
+
+   if (sigrt_count)
+     {
+       free((sig_atomic_t *) sigrt_count);
+       sigrt_count = NULL;
+     }
+
+   for (i = 0; i < MAXSIGQ; i++)
+     {
+       if (sigrt_info[i])
+         {
+            free((siginfo_t *) sigrt_info[i]);
+            sigrt_info[i] = NULL;
+         }
+     }
+#endif
+}
+
+void
+_ecore_signal_init(void)
+{
+#ifdef SIGRTMIN
+   int i, num = SIGRTMAX - SIGRTMIN;
+#endif
+
+   _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
+   _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
+   _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
+   _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
+   _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
+   _ecore_signal_callback_set(SIGHUP,  _ecore_signal_callback_sighup);
+   _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
+   _ecore_signal_callback_set(SIGINT,  _ecore_signal_callback_sigint);
+   _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
+#ifdef SIGPWR
+   _ecore_signal_callback_set(SIGPWR,  _ecore_signal_callback_sigpwr);
+#endif
+
+#ifdef SIGRTMIN
+   sigrt_count = calloc(1, sizeof(sig_atomic_t) * num);
+   assert(sigrt_count);
+
+   for (i = 0; i < MAXSIGQ; i++)
+     {
+       sigrt_info[i] = calloc(1, sizeof(siginfo_t) * num);
+       assert(sigrt_info[i]);
+     }
+
+   for (i = 0; i < num; i++)
+      _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt);
+#endif
+}
+
+int
+_ecore_signal_count_get(void)
+{
+   return sig_count;
+}
+
+void
+_ecore_signal_call(void)
+{
+#ifdef SIGRTMIN
+   int i, num = SIGRTMAX - SIGRTMIN;
+#endif
+   volatile sig_atomic_t n;
+   sigset_t oldset, newset;
+
+   if (sig_count == 0) return;
+   sigemptyset(&newset);
+   sigaddset(&newset, SIGPIPE);
+   sigaddset(&newset, SIGALRM);
+   sigaddset(&newset, SIGCHLD);
+   sigaddset(&newset, SIGUSR1);
+   sigaddset(&newset, SIGUSR2);
+   sigaddset(&newset, SIGHUP);
+   sigaddset(&newset, SIGQUIT);
+   sigaddset(&newset, SIGINT);
+   sigaddset(&newset, SIGTERM);
+#ifdef SIGPWR
+   sigaddset(&newset, SIGPWR);
+#endif
+#ifdef SIGRTMIN
+   for (i = 0; i < num; i++)
+     sigaddset(&newset, SIGRTMIN + i);
+#endif
+   sigprocmask(SIG_BLOCK, &newset, &oldset);
+   if (sigchld_count > MAXSIGQ)
+     WRN("%i SIGCHLD in queue. max queue size %i. losing "
+         "siginfo for extra signals.", sigchld_count, MAXSIGQ);
+   for (n = 0; n < sigchld_count; n++)
+     {
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+         {
+            Ecore_Exe_Event_Del *e;
+
+            /* FIXME: If this process is set respawn, respawn with a suitable backoff
+             * period for those that need too much respawning.
+             */
+            e = _ecore_exe_event_del_new();
+            if (e)
+              {
+                 if (WIFEXITED(status))
+                   {
+                      e->exit_code = WEXITSTATUS(status);
+                      e->exited = 1;
+                   }
+                 else if (WIFSIGNALED(status))
+                   {
+                      e->exit_signal = WTERMSIG(status);
+                      e->signalled = 1;
+                   }
+                 e->pid = pid;
+                 e->exe = _ecore_exe_find(pid);
+
+                 if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
+                   e->data = sigchld_info[n]; /* No need to clone this. */
+
+                  if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
+                     {
+                       /* We want to report the Last Words of the exe, so delay this event.
+                        * This is twice as relevant for stderr.
+                        * There are three possibilities here -
+                        *  1 There are no Last Words.
+                        *  2 There are Last Words, they are not ready to be read.
+                        *  3 There are Last Words, they are ready to be read.
+                        *
+                        * For 1 we don't want to delay, for 3 we want to delay.
+                        * 2 is the problem.  If we check for data now and there
+                        * is none, then there is no way to differentiate 1 and 2.
+                        * If we don't delay, we may loose data, but if we do delay,
+                        * there may not be data and the exit event never gets sent.
+                        *
+                        * Any way you look at it, there has to be some time passed
+                        * before the exit event gets sent.  So the strategy here is
+                        * to setup a timer event that will send the exit event after
+                        * an arbitrary, but brief, time.
+                        *
+                        * This is probably paranoid, for the less paraniod, we could
+                        * check to see for Last Words, and only delay if there are any.
+                        * This has it's own set of problems.
+                        */
+                        Ecore_Timer *doomsday_clock;
+
+                        doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe);
+                        IF_FN_DEL(ecore_timer_del, doomsday_clock);
+                        _ecore_exe_doomsday_clock_set(e->exe, ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e));
+                     }
+                 else
+                   {
+                      _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
+                                  _ecore_exe_event_del_free, NULL);
+                   }
+              }
+         }
+       sig_count--;
+     }
+   sigchld_count = 0;
+
+   if (sigusr1_count > MAXSIGQ)
+     WRN("%i SIGUSR1 in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
+   for (n = 0; n < sigusr1_count; n++)
+     {
+       Ecore_Event_Signal_User *e;
+
+       e = _ecore_event_signal_user_new();
+       if (e)
+         {
+            e->number = 1;
+
+            if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
+              e->data = sigusr1_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigusr1_count = 0;
+
+   if (sigusr2_count > MAXSIGQ)
+     WRN("%i SIGUSR2 in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
+   for (n = 0; n < sigusr2_count; n++)
+     {
+       Ecore_Event_Signal_User *e;
+
+       e = _ecore_event_signal_user_new();
+       if (e)
+         {
+            e->number = 2;
+
+            if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
+              e->data = sigusr2_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigusr2_count = 0;
+
+   if (sighup_count > MAXSIGQ)
+     WRN("%i SIGHUP in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sighup_count, MAXSIGQ);
+   for (n = 0; n < sighup_count; n++)
+     {
+       Ecore_Event_Signal_Hup *e;
+
+       e = _ecore_event_signal_hup_new();
+       if (e)
+         {
+            if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
+              e->data = sighup_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sighup_count = 0;
+
+   if (sigquit_count > MAXSIGQ)
+     WRN("%i SIGQUIT in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigquit_count, MAXSIGQ);
+   for (n = 0; n < sigquit_count; n++)
+     {
+       Ecore_Event_Signal_Exit *e;
+
+       e = _ecore_event_signal_exit_new();
+       if (e)
+         {
+            e->quit = 1;
+
+            if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
+              e->data = sigquit_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigquit_count = 0;
+
+   if (sigint_count > MAXSIGQ)
+     WRN("%i SIGINT in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigint_count, MAXSIGQ);
+   for (n = 0; n < sigint_count; n++)
+     {
+       Ecore_Event_Signal_Exit *e;
+
+       e = _ecore_event_signal_exit_new();
+       if (e)
+         {
+            e->interrupt = 1;
+
+            if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
+              e->data = sigint_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigint_count = 0;
+
+   if (sigterm_count > MAXSIGQ)
+     WRN("%i SIGTERM in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigterm_count, MAXSIGQ);
+   for (n = 0; n < sigterm_count; n++)
+     {
+       Ecore_Event_Signal_Exit *e;
+
+       e = _ecore_event_signal_exit_new();
+       if (e)
+         {
+            e->terminate = 1;
+
+            if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
+              e->data = sigterm_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigterm_count = 0;
+
+#ifdef SIGPWR
+   if (sigpwr_count > MAXSIGQ)
+     WRN("%i SIGPWR in queue. max queue size %i. losing "
+        "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
+   for (n = 0; n < sigpwr_count; n++)
+     {
+       Ecore_Event_Signal_Power *e;
+
+       e = _ecore_event_signal_power_new();
+       if (e)
+         {
+            if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
+              e->data = sigpwr_info[n];
+
+            ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL);
+         }
+       sig_count--;
+     }
+   sigpwr_count = 0;
+#endif
+
+#ifdef SIGRTMIN
+   for (i = 0; i < num; i++)
+     {
+       if (sigrt_count[i] > MAXSIGQ)
+         WRN("%i SIGRT%i in queue. max queue size %i. losing "
+             "siginfo for extra signals.", i + 1, sigrt_count[i], MAXSIGQ);
+       for (n = 0; n < sigrt_count[i]; n++)
+         {
+            Ecore_Event_Signal_Realtime *e;
+
+            if ((e = _ecore_event_signal_realtime_new()))
+              {
+                 e->num = i;
+
+                 if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo))
+                   e->data = sigrt_info[n][i];
+
+                 ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL);
+              }
+            sig_count--;
+         }
+       sigrt_count[i] = 0;
+     }
+#endif
+   sigprocmask(SIG_SETMASK, &oldset, NULL);
+}
+
+static void
+_ecore_signal_callback_set(int sig, Signal_Handler func)
+{
+   struct sigaction  sa;
+
+   sa.sa_sigaction = func;
+   sa.sa_flags = SA_RESTART | SA_SIGINFO;
+   sigemptyset(&sa.sa_mask);
+   sigaction(sig, &sa, NULL);
+}
+
+static void
+_ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__)
+{
+}
+
+static void
+_ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigchld_info[n] = *si;
+       else
+         sigchld_info[n].si_signo = 0;
+     }
+
+   sigchld_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigusr1_info[n] = *si;
+       else
+         sigusr1_info[n].si_signo = 0;
+     }
+   sigusr1_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigusr2_info[n] = *si;
+       else
+         sigusr2_info[n].si_signo = 0;
+     }
+   sigusr2_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sighup_info[n] = *si;
+       else
+         sighup_info[n].si_signo = 0;
+     }
+   sighup_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigquit_info[n] = *si;
+       else
+         sigquit_info[n].si_signo = 0;
+     }
+   sigquit_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigint_info[n] = *si;
+       else
+         sigint_info[n].si_signo = 0;
+     }
+   sigint_count++;
+   sig_count++;
+}
+
+static void
+_ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigterm_info[n] = *si;
+       else
+         sigterm_info[n].si_signo = 0;
+     }
+   sigterm_count++;
+   sig_count++;
+}
+
+#ifdef SIGPWR
+static void
+_ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigpwr_info[n] = *si;
+       else
+         sigpwr_info[n].si_signo = 0;
+     }
+   sigpwr_count++;
+   sig_count++;
+}
+#endif
+
+#ifdef SIGRTMIN
+static void
+_ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
+{
+   volatile sig_atomic_t n;
+   n = sigchld_count;
+   if (n < MAXSIGQ)
+     {
+       if (si)
+         sigrt_info[n][sig - SIGRTMIN] = *si;
+       else
+         sigrt_info[n][sig - SIGRTMIN].si_signo = 0;
+     }
+   sigrt_count[sig - SIGRTMIN]++;
+   sig_count++;
+}
+#endif
+
+static int
+_ecore_signal_exe_exit_delay(void *data)
+{
+   Ecore_Exe_Event_Del *e;
+
+   e = data;
+   if (e)
+     {
+       _ecore_exe_doomsday_clock_set(e->exe, NULL);
+       _ecore_event_add(ECORE_EXE_EVENT_DEL, e,
+                        _ecore_exe_event_del_free, NULL);
+     }
+   return 0;
+}
diff --git a/src/lib/ecore/ecore_thread.c b/src/lib/ecore/ecore_thread.c
new file mode 100644 (file)
index 0000000..8c62db4
--- /dev/null
@@ -0,0 +1,323 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#ifdef EFL_HAVE_PTHREAD
+# include <pthread.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#ifdef EFL_HAVE_PTHREAD
+typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
+typedef struct _Ecore_Pthread_Data Ecore_Pthread_Data;
+typedef struct _Ecore_Pthread Ecore_Pthread;
+
+struct _Ecore_Pthread_Worker
+{
+   void (*func_heavy)(void *data);
+   void (*func_end)(void *data);
+   void (*func_cancel)(void *data);
+
+   const void *data;
+
+   Eina_Bool cancel : 1;
+};
+
+struct _Ecore_Pthread_Data
+{
+   Ecore_Pipe *p;
+   pthread_t thread;
+};
+#endif
+
+static int _ecore_thread_count_max = 0;
+static int ECORE_THREAD_PIPE_DEL = 0;
+
+#ifdef EFL_HAVE_PTHREAD
+static int _ecore_thread_count = 0;
+static Eina_List *_ecore_thread_data = NULL;
+static Eina_List *_ecore_thread = NULL;
+static Ecore_Event_Handler *del_handler = NULL;
+
+static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void
+_ecore_thread_pipe_free(void *data __UNUSED__, void *event)
+{
+   Ecore_Pipe *p = event;
+
+   ecore_pipe_del(p);
+}
+
+static int
+_ecore_thread_pipe_del(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+   /* This is a hack to delay pipe destruction until we are out of it's internal loop. */
+   return 0;
+}
+
+static void
+_ecore_thread_end(Ecore_Pthread_Data *pth)
+{
+   Ecore_Pipe *p;
+
+   if (pthread_join(pth->thread, (void**) &p) != 0)
+     return ;
+
+   _ecore_thread = eina_list_remove(_ecore_thread, pth);
+
+   ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL);
+}
+
+static void *
+_ecore_thread_worker(Ecore_Pthread_Data *pth)
+{
+   Ecore_Pthread_Worker *work;
+
+   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+   pthread_mutex_lock(&_mutex);
+   _ecore_thread_count++;
+   pthread_mutex_unlock(&_mutex);
+
+ on_error:
+
+   while (_ecore_thread_data)
+     {
+       pthread_mutex_lock(&_mutex);
+
+       if (!_ecore_thread_data)
+         {
+            pthread_mutex_unlock(&_mutex);
+            break;
+         }
+
+       work = eina_list_data_get(_ecore_thread_data);
+       _ecore_thread_data = eina_list_remove_list(_ecore_thread_data, _ecore_thread_data);
+
+       pthread_mutex_unlock(&_mutex);
+
+       work->func_heavy((void*) work->data);
+
+       ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker*));
+     }
+
+   pthread_mutex_lock(&_mutex);
+   if (_ecore_thread_data)
+     {
+       pthread_mutex_unlock(&_mutex);
+       goto on_error;
+     }
+   _ecore_thread_count--;
+
+   pthread_mutex_unlock(&_mutex);
+
+   work = malloc(sizeof (Ecore_Pthread_Worker));
+   if (!work) return NULL;
+
+   work->data = pth;
+   work->func_heavy = NULL;
+   work->func_end = (void*) _ecore_thread_end;
+   work->func_cancel = NULL;
+   work->cancel = EINA_FALSE;
+
+   ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker*));
+
+   return pth->p;
+}
+
+static void
+_ecore_thread_handler(void *data __UNUSED__, void *buffer, unsigned int nbyte)
+{
+   Ecore_Pthread_Worker *work;
+
+   if (nbyte != sizeof (Ecore_Pthread_Worker*)) return ;
+
+   work = *(Ecore_Pthread_Worker**)buffer;
+
+   if (work->cancel)
+     {
+       if (work->func_cancel)
+         work->func_cancel((void*) work->data);
+     }
+   else
+     {
+       work->func_end((void*) work->data);
+     }
+
+   free(work);
+}
+#endif
+
+void
+_ecore_thread_init(void)
+{
+   _ecore_thread_count_max = eina_cpu_count();
+   if (_ecore_thread_count_max <= 0)
+     _ecore_thread_count_max = 1;
+
+   ECORE_THREAD_PIPE_DEL = ecore_event_type_new();
+#ifdef EFL_HAVE_PTHREAD
+   del_handler = ecore_event_handler_add(ECORE_THREAD_PIPE_DEL, _ecore_thread_pipe_del, NULL);
+#endif
+}
+
+void
+_ecore_thread_shutdown(void)
+{
+   /* FIXME: If function are still running in the background, should we kill them ? */
+#ifdef EFL_HAVE_PTHREAD
+   Ecore_Pthread_Worker *work;
+   Ecore_Pthread_Data *pth;
+
+   pthread_mutex_lock(&_mutex);
+
+   EINA_LIST_FREE(_ecore_thread_data, work)
+     {
+       if (work->func_cancel)
+         work->func_cancel((void*)work->data);
+       free(work);
+     }
+
+   pthread_mutex_unlock(&_mutex);
+
+   EINA_LIST_FREE(_ecore_thread, pth)
+     {
+       Ecore_Pipe *p;
+
+       pthread_cancel(pth->thread);
+       pthread_join(pth->thread, (void **) &p);
+
+       ecore_pipe_del(pth->p);
+     }
+
+   ecore_event_handler_del(del_handler);
+   del_handler = NULL;
+#endif
+}
+
+/*
+ * ecore_thread_run provide a facility for easily managing heavy task in a
+ * parallel thread. You should provide two function, the first one, func_heavy,
+ * that will do the heavy work in another thread (so you should not use the
+ * EFL in it except Eina if you are carefull), and the second one, func_end,
+ * that will be called in Ecore main loop when func_heavy is done. So you
+ * can use all the EFL inside this function.
+ *
+ * Be aware, that you can't make assumption on the result order of func_end
+ * after many call to ecore_thread_run, as we start as much thread as the
+ * host CPU can handle.
+ */
+EAPI Ecore_Thread *
+ecore_thread_run(void (*func_heavy)(void *data),
+                void (*func_end)(void *data),
+                void (*func_cancel)(void *data),
+                const void *data)
+{
+#ifdef EFL_HAVE_PTHREAD
+   Ecore_Pthread_Worker *work;
+   Ecore_Pthread_Data *pth;
+
+   work = malloc(sizeof (Ecore_Pthread_Worker));
+   if (!work)
+     {
+        func_cancel((void*) data);
+       return NULL;
+     }
+
+   work->func_heavy = func_heavy;
+   work->func_end = func_end;
+   work->func_cancel = func_cancel;
+   work->cancel = EINA_FALSE;
+   work->data = data;
+
+   pthread_mutex_lock(&_mutex);
+   _ecore_thread_data = eina_list_append(_ecore_thread_data, work);
+
+   if (_ecore_thread_count == _ecore_thread_count_max)
+     {
+       pthread_mutex_unlock(&_mutex);
+       return (Ecore_Thread*) work;
+     }
+
+   pthread_mutex_unlock(&_mutex);
+
+   /* One more thread could be created. */
+   pth = malloc(sizeof (Ecore_Pthread_Data));
+   if (!pth)
+     goto on_error;
+
+   pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
+
+   if (pthread_create(&pth->thread, NULL, (void*) _ecore_thread_worker, pth) == 0)
+     return (Ecore_Thread*) work;
+
+ on_error:
+   if (_ecore_thread_count == 0)
+     {
+       if (work->func_cancel)
+         work->func_cancel((void*) work->data);
+       free(work);
+     }
+   return NULL;
+#else
+   /*
+     If no thread and as we don't want to break app that rely on this
+     facility, we will lock the interface until we are done.
+    */
+   func_heavy((void *)data);
+   func_end((void *)data);
+
+   return NULL;
+#endif
+}
+
+/*
+ * ecore_thread_cancel give the possibility to cancel a task still running. It
+ * will return EINA_FALSE, if the destruction is delayed or EINA_TRUE if it is
+ * cancelled after this call.
+ *
+ * You should use this function only in the main loop.
+ *
+ * func_end, func_cancel will destroy the handler, so don't use it after.
+ * And if ecore_thread_cancel return EINA_TRUE, you should not use Ecore_Thread also.
+ */
+EAPI Eina_Bool
+ecore_thread_cancel(Ecore_Thread *thread)
+{
+#ifdef EFL_HAVE_PTHREAD
+   Ecore_Pthread_Worker *work;
+   Eina_List *l;
+
+   pthread_mutex_lock(&_mutex);
+
+   EINA_LIST_FOREACH(_ecore_thread_data, l, work)
+     if ((void*) work == (void*) thread)
+       {
+         _ecore_thread_data = eina_list_remove_list(_ecore_thread_data, l);
+
+         pthread_mutex_unlock(&_mutex);
+
+         if (work->func_cancel)
+           work->func_cancel((void*) work->data);
+         free(work);
+
+         return EINA_TRUE;
+       }
+
+   pthread_mutex_unlock(&_mutex);
+
+   /* Delay the destruction */
+   ((Ecore_Pthread_Worker*)thread)->cancel = EINA_TRUE;
+   return EINA_FALSE;
+#else
+   return EINA_TRUE;
+#endif
+}
diff --git a/src/lib/ecore/ecore_time.c b/src/lib/ecore/ecore_time.c
new file mode 100644 (file)
index 0000000..70abb26
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+
+/* FIXME: clock_gettime() is an option... */
+
+/**
+ * Retrieves the current system time as a floating point value in seconds.
+ *
+ * Also see ecore_loop_time_get().
+ *
+ * @return  The number of seconds since 12.00AM 1st January 1970.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI double
+ecore_time_get(void)
+{
+#ifdef HAVE_EVIL
+  return evil_time_get();
+#else
+# ifdef HAVE_GETTIMEOFDAY
+   struct timeval      timev;
+
+   gettimeofday(&timev, NULL);
+   return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+# else
+#  error "Your platform isn't supported yet"
+# endif
+#endif
+}
+
+double _ecore_loop_time = -1.0;
+
+/**
+ * Retrieves the time at which the last loop stopped waiting for timeouts or events
+ *
+ * This gets the time (since Jan 1st, 1970, 12:00AM) that the main loop ceased
+ * waiting for timouts and/or events to come in or for signals or any other
+ * interrupt source. This should be considered a reference point for all
+ * time based activity that should calculate its timepoint from the return
+ * of ecore_loop_time_get(). use this UNLESS you absolutely must get the
+ * current actual timepoint - then use ecore_time_get(). If this is called
+ * before any loop has ever been run, then it will call ecore_time_get() for
+ * you the first time and thus have an initial time reference.
+ *
+ * @return  The number of seconds since 12.00AM 1st January 1970.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI double
+ecore_loop_time_get(void)
+{
+   return _ecore_loop_time;
+}
diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c
new file mode 100644 (file)
index 0000000..8d13c06
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+
+struct _Ecore_Timer
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   double          in;
+   double          at;
+   double          pending;
+   int           (*func) (void *data);
+   void           *data;
+
+   int             references;
+   unsigned char   delete_me : 1;
+   unsigned char   just_added : 1;
+   unsigned char   frozen : 1;
+};
+
+
+static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data);
+
+static int          timers_added = 0;
+static int          timers_delete_me = 0;
+static Ecore_Timer *timers = NULL;
+static Ecore_Timer *timer_current = NULL;
+static Ecore_Timer *suspended = NULL;
+static double       last_check = 0.0;
+static double       precision = 10.0 / 1000000.0;
+
+/**
+ * @defgroup Ecore_Time_Group Ecore Time Functions
+ *
+ * Functions that deal with time.  These functions include those that simply
+ * retrieve it in a given format, and those that create events based on it.
+ */
+
+/**
+ * Retrieves the current precision used by timer infrastructure.
+ *
+ * @see ecore_timer_precision_set()
+ */
+EAPI double
+ecore_timer_precision_get(void)
+{
+   return precision;
+}
+
+/**
+ * Sets the precision to be used by timer infrastructure.
+ *
+ * When system calculates time to expire the next timer we'll be able
+ * to delay the timer by the given amount so more timers will fit in
+ * the same dispatch, waking up the system less often and thus being
+ * able to save power.
+ *
+ * Be aware that kernel may delay delivery even further, these delays
+ * are always possible due other tasks having higher priorities or
+ * other scheduler policies.
+ *
+ * Example:
+ *  We have 2 timers, one that expires in a 2.0s and another that
+ *  expires in 2.1s, if precision is 0.1s, then the Ecore will request
+ *  for the next expire to happen in 2.1s and not 2.0s and another one
+ *  of 0.1 as it would before.
+ *
+ * @note Ecore is smart enough to see if there are timers in the
+ * precision range, if it does not, in our example if no second timer
+ * in (T + precision) existed, then it would use the minimum timeout.
+ *
+ * @param value allowed introduced timeout delay, in seconds.
+ */
+EAPI void
+ecore_timer_precision_set(double value)
+{
+   if (value < 0.0)
+     {
+       ERR("Precision %f less than zero, ignored", value);
+       return;
+     }
+   precision = value;
+}
+
+/**
+ * Creates a timer to call the given function in the given period of time.
+ * @param   in   The interval in seconds.
+ * @param   func The given function.  If @p func returns 1, the timer is
+ *               rescheduled for the next interval @p in.
+ * @param   data Data to pass to @p func when it is called.
+ * @return  A timer object on success.  @c NULL on failure.
+ * @ingroup Ecore_Time_Group
+ *
+ * This function adds a timer and returns its handle on success and NULL on
+ * failure. The function @p func will be called every @p in seconds. The
+ * function will be passed the @p data pointer as its parameter.
+ *
+ * When the timer @p func is called, it must return a value of either 1
+ * (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL).
+ * If it returns 1, it will be called again at the next tick, or if it returns
+ * 0 it will be deleted automatically making any references/handles for it
+ * invalid.
+ */
+EAPI Ecore_Timer *
+ecore_timer_add(double in, int (*func) (void *data), const void *data)
+{
+   double now;
+   Ecore_Timer *timer;
+
+   if (!func) return NULL;
+   if (in < 0.0) in = 0.0;
+   timer = calloc(1, sizeof(Ecore_Timer));
+   if (!timer) return NULL;
+   ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
+   now = ecore_time_get();
+   _ecore_timer_set(timer, now + in, in, func, (void *)data);
+   return timer;
+}
+
+/**
+ * Creates a timer to call the given function in the given period of time.
+ * @param   in   The interval in seconds from current loop time.
+ * @param   func The given function.  If @p func returns 1, the timer is
+ *               rescheduled for the next interval @p in.
+ * @param   data Data to pass to @p func when it is called.
+ * @return  A timer object on success.  @c NULL on failure.
+ * @ingroup Ecore_Time_Group
+ *
+ * This is the same as ecore_timer_add(), but "now" is the time from
+ * ecore_loop_time_get() not ecore_time_get() as ecore_timer_add() uses. See
+ * ecore_timer_add() for more details.
+ */
+EAPI Ecore_Timer *
+ecore_timer_loop_add(double in, int (*func) (void *data), const void *data)
+{
+   double now;
+   Ecore_Timer *timer;
+
+   if (!func) return NULL;
+   if (in < 0.0) in = 0.0;
+   timer = calloc(1, sizeof(Ecore_Timer));
+   if (!timer) return NULL;
+   ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
+   now = ecore_loop_time_get();
+   _ecore_timer_set(timer, now + in, in, func, (void *)data);
+   return timer;
+}
+
+/**
+ * Delete the specified timer from the timer list.
+ * @param   timer The timer to delete.
+ * @return  The data pointer set for the timer when @ref ecore_timer_add was
+ *          called.  @c NULL is returned if the function is unsuccessful.
+ * @ingroup Ecore_Time_Group
+ *
+ * Note: @p timer must be a valid handle. If the timer function has already
+ * returned 0, the handle is no longer valid (and does not need to be delete).
+ */
+EAPI void *
+ecore_timer_del(Ecore_Timer *timer)
+{
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                        "ecore_timer_del");
+       return NULL;
+     }
+
+   if (timer->frozen && !timer->references)
+     {
+       void *data = timer->data;
+
+       suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
+
+       if (timer->delete_me)
+         timers_delete_me--;
+
+       free(timer);
+       return data;
+     }
+
+   if (timer->delete_me) return timer->data;
+   timers_delete_me++;
+   timer->delete_me = 1;
+   return timer->data;
+}
+
+/**
+ * Change the interval the timer ticks of. If set during
+ * a timer call, this will affect the next interval.
+ *
+ * @param   timer The timer to change.
+ * @param   in    The interval in seconds.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI void
+ecore_timer_interval_set(Ecore_Timer *timer, double in)
+{
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                        "ecore_timer_interval_set");
+       return;
+     }
+   timer->in = in;
+}
+
+/**
+ * Get the interval the timer ticks on.
+ *
+ * @param   timer The timer to retrieve the interval from
+ * @return  The interval on success. -1 on failure.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI double
+ecore_timer_interval_get(Ecore_Timer *timer)
+{
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                        "ecore_timer_interval_get");
+       return -1.0;
+     }
+
+   return timer->in;
+}
+
+/**
+ * Add some delay for the next occurence of a timer.
+ * This doesn't affect the interval of a timer.
+ *
+ * @param   timer The timer to change.
+ * @param   add   The dalay to add to the next iteration.
+ * @ingroup Ecore_Time_Group
+ */
+EAPI void
+ecore_timer_delay(Ecore_Timer *timer, double add)
+{
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                        "ecore_timer_delay");
+       return;
+     }
+
+   if (timer->frozen)
+     {
+       timer->pending += add;
+     }
+   else
+     {
+       timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
+       _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
+     }
+}
+
+/**
+ * Get the pending time regarding a timer.
+ *
+ * @param      timer The timer to learn from.
+ * @ingroup    Ecore_Time_Group
+ */
+EAPI double
+ecore_timer_pending_get(Ecore_Timer *timer)
+{
+   double      now;
+
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                        "ecore_timer_pending_get");
+       return 0;
+     }
+
+   now = ecore_time_get();
+
+   if (timer->frozen)
+     return timer->pending;
+   return timer->at - now;
+}
+
+/**
+ *
+ *
+ */
+EAPI void
+ecore_timer_freeze(Ecore_Timer *timer)
+{
+   double now;
+
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                         "ecore_timer_freeze");
+        return ;
+     }
+
+   /* Timer already frozen */
+   if (timer->frozen)
+     return ;
+
+   timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
+   suspended = (Ecore_Timer *) eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
+
+   now = ecore_time_get();
+
+   timer->pending = timer->at - now;
+   timer->at = 0.0;
+   timer->frozen = 1;
+}
+
+EAPI void
+ecore_timer_thaw(Ecore_Timer *timer)
+{
+   double now;
+
+   if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
+     {
+       ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
+                         "ecore_timer_thaw");
+        return ;
+     }
+
+   /* Timer not frozen */
+   if (!timer->frozen)
+     return ;
+
+   suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
+   now = ecore_time_get();
+
+   _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
+}
+
+void
+_ecore_timer_shutdown(void)
+{
+   Ecore_Timer *timer;
+
+   while ((timer = timers))
+     {
+       timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timers));
+       ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
+       free(timer);
+     }
+
+   while ((timer = suspended))
+     {
+        suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(suspended));
+        ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
+        free(timer);
+     }
+
+   timer_current = NULL;
+}
+
+void
+_ecore_timer_cleanup(void)
+{
+   Ecore_Timer *l;
+   int in_use = 0;
+
+   if (!timers_delete_me) return;
+   for (l = timers; l;)
+     {
+       Ecore_Timer *timer = l;
+
+       l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
+       if (timer->delete_me)
+         {
+            if (timer->references)
+              {
+                 in_use++;
+                 continue;
+              }
+            timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
+            ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
+            free(timer);
+            timers_delete_me--;
+            if (timers_delete_me == 0) return;
+         }
+     }
+   for (l = suspended; l;)
+     {
+       Ecore_Timer *timer = l;
+
+       l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
+       if (timer->delete_me)
+         {
+            if (timer->references)
+              {
+                 in_use++;
+                 continue;
+              }
+            suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
+            ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
+            free(timer);
+            timers_delete_me--;
+            if (timers_delete_me == 0) return;
+         }
+     }
+
+   if ((!in_use) && (timers_delete_me))
+     {
+       ERR("%d timers to delete, but they were not found! reset counter.",
+           timers_delete_me);
+       timers_delete_me = 0;
+     }
+}
+
+void
+_ecore_timer_enable_new(void)
+{
+   Ecore_Timer *timer;
+
+   if (!timers_added) return;
+   timers_added = 0;
+   EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0;
+}
+
+int
+_ecore_timers_exists(void)
+{
+   Ecore_Timer *timer = timers;
+
+   while ((timer) && (timer->delete_me))
+     timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
+
+   return !!timer;
+}
+
+static inline Ecore_Timer *
+_ecore_timer_first_get(void)
+{
+   Ecore_Timer *timer = timers;
+
+   while ((timer) && ((timer->delete_me) || (timer->just_added)))
+     timer = (Ecore_Timer *) EINA_INLIST_GET(timer)->next;
+
+   return timer;
+}
+
+static inline Ecore_Timer *
+_ecore_timer_after_get(Ecore_Timer *base)
+{
+   Ecore_Timer *timer = (Ecore_Timer *) EINA_INLIST_GET(base)->next;
+   double maxtime = base->at + precision;
+
+   while ((timer) && ((timer->delete_me) || (timer->just_added)) && (timer->at <= maxtime))
+     timer = (Ecore_Timer *) EINA_INLIST_GET(timer)->next;
+
+   if ((!timer) || (timer->at > maxtime))
+     return NULL;
+
+   return timer;
+}
+
+double
+_ecore_timer_next_get(void)
+{
+   double now;
+   double in;
+   Ecore_Timer *first, *second;
+
+   first = _ecore_timer_first_get();
+   if (!first) return -1;
+
+   second = _ecore_timer_after_get(first);
+   if (second)
+     first = second;
+
+   now = ecore_loop_time_get();
+   in = first->at - now;
+   if (in < 0) in = 0;
+   return in;
+}
+
+int
+_ecore_timer_call(double when)
+{
+   if (!timers) return 0;
+   if (last_check > when)
+     {
+       Ecore_Timer *timer;
+       /* User set time backwards */
+       EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
+     }
+   last_check = when;
+
+   if (!timer_current)
+     {
+       /* regular main loop, start from head */
+       timer_current = timers;
+     }
+   else
+     {
+       /* recursive main loop, continue from where we were */
+       timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
+     }
+
+   while (timer_current)
+     {
+       Ecore_Timer *timer = timer_current;
+
+       if (timer->at > when)
+         {
+            timer_current = NULL; /* ended walk, next should restart. */
+            return 0;
+         }
+
+       if ((timer->just_added) || (timer->delete_me))
+         {
+            timer_current = (Ecore_Timer*)EINA_INLIST_GET(timer_current)->next;
+            continue;
+         }
+
+       timer->references++;
+       if (!timer->func(timer->data)) ecore_timer_del(timer);
+       timer->references--;
+
+       if (timer_current) /* may have changed in recursive main loops */
+         timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
+
+       if ((!timer->delete_me) && (!timer->frozen))
+         {
+            timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
+
+            /* if the timer would have gone off more than 15 seconds ago,
+             * assume that the system hung and set the timer to go off
+             * timer->in from now. this handles system hangs, suspends
+             * and more, so ecore will only "replay" the timers while
+             * the system is suspended if it is suspended for less than
+             * 15 seconds (basically). this also handles if the process
+             * is stopped in a debugger or IO and other handling gets
+             * really slow within the main loop.
+             */
+            if ((timer->at + timer->in) < (when - 15.0))
+              _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
+            else
+              _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
+         }
+     }
+   return 0;
+}
+
+static void
+_ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data)
+{
+   Ecore_Timer *t2;
+
+   timers_added = 1;
+   timer->at = at;
+   timer->in = in;
+   timer->func = func;
+   timer->data = data;
+   timer->just_added = 1;
+   timer->frozen = 0;
+   timer->pending = 0.0;
+   if (timers)
+     {
+       EINA_INLIST_REVERSE_FOREACH(EINA_INLIST_GET(timers), t2)
+         {
+            if (timer->at > t2->at)
+              {
+                 timers = (Ecore_Timer *) eina_inlist_append_relative(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer), EINA_INLIST_GET(t2));
+                 return;
+              }
+         }
+     }
+   timers = (Ecore_Timer *) eina_inlist_prepend(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
+}
diff --git a/src/lib/ecore_cocoa/Ecore_Cocoa.h b/src/lib/ecore_cocoa/Ecore_Cocoa.h
new file mode 100644 (file)
index 0000000..a3a11fd
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+*/
+
+#ifndef _ECORE_COCOA_H
+#define _ECORE_COCOA_H
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Ecore_Cocoa_Window Ecore_Cocoa_Window;
+
+EAPI extern int ECORE_COCOA_EVENT_GOT_FOCUS;
+EAPI extern int ECORE_COCOA_EVENT_LOST_FOCUS;
+EAPI extern int ECORE_COCOA_EVENT_RESIZE;
+EAPI extern int ECORE_COCOA_EVENT_EXPOSE;
+
+typedef struct _Ecore_Cocoa_Event_Video_Resize Ecore_Cocoa_Event_Video_Resize;
+struct _Ecore_Cocoa_Event_Video_Resize
+{
+   int             w;
+   int             h;
+};
+
+
+/* Core */
+
+EAPI int  ecore_cocoa_init(const char *name);
+EAPI int  ecore_cocoa_shutdown(void);
+EAPI void ecore_cocoa_feed_events(void);
+
+/* Window */
+
+EAPI Ecore_Cocoa_Window *ecore_cocoa_window_new(int x,
+                                                int y,
+                                                int width,
+                                                int height);
+
+EAPI void ecore_cocoa_window_free(Ecore_Cocoa_Window *window);
+
+EAPI void *ecore_cocoa_window_hwnd_get(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_move(Ecore_Cocoa_Window *window,
+                                  int                 x,
+                                  int                 y);
+
+EAPI void ecore_cocoa_window_resize(Ecore_Cocoa_Window *window,
+                                    int                 width,
+                                    int                 height);
+
+EAPI void ecore_cocoa_window_move_resize(Ecore_Cocoa_Window *window,
+                                         int                 x,
+                                         int                 y,
+                                         int                 width,
+                                         int                 height);
+
+EAPI void ecore_cocoa_window_geometry_get(Ecore_Cocoa_Window *window,
+                                          int                *x,
+                                          int                *y,
+                                          int                *width,
+                                          int                *height);
+
+EAPI void ecore_cocoa_window_size_get(Ecore_Cocoa_Window *window,
+                                      int                *width,
+                                      int                *height);
+
+EAPI void ecore_cocoa_window_size_min_set(Ecore_Cocoa_Window *window,
+                                          unsigned int        min_width,
+                                          unsigned int        min_height);
+
+EAPI void ecore_cocoa_window_size_min_get(Ecore_Cocoa_Window *window,
+                                          unsigned int       *min_width,
+                                          unsigned int       *min_height);
+
+EAPI void ecore_cocoa_window_size_max_set(Ecore_Cocoa_Window *window,
+                                          unsigned int        max_width,
+                                          unsigned int        max_height);
+
+EAPI void ecore_cocoa_window_size_max_get(Ecore_Cocoa_Window *window,
+                                          unsigned int       *max_width,
+                                          unsigned int       *max_height);
+
+EAPI void ecore_cocoa_window_size_base_set(Ecore_Cocoa_Window *window,
+                                           unsigned int        base_width,
+                                           unsigned int        base_height);
+
+EAPI void ecore_cocoa_window_size_base_get(Ecore_Cocoa_Window *window,
+                                           unsigned int       *base_width,
+                                           unsigned int       *base_height);
+
+EAPI void ecore_cocoa_window_size_step_set(Ecore_Cocoa_Window *window,
+                                           unsigned int        step_width,
+                                           unsigned int        step_height);
+
+EAPI void ecore_cocoa_window_size_step_get(Ecore_Cocoa_Window *window,
+                                           unsigned int       *step_width,
+                                           unsigned int       *step_height);
+
+EAPI void ecore_cocoa_window_show(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_hide(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_raise(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_lower(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_title_set(Ecore_Cocoa_Window *window,
+                                       const char         *title);
+
+EAPI void ecore_cocoa_window_focus_set(Ecore_Cocoa_Window *window);
+
+EAPI void ecore_cocoa_window_iconified_set(Ecore_Cocoa_Window *window,
+                                           int                 on);
+
+EAPI void ecore_cocoa_window_borderless_set(Ecore_Cocoa_Window *window,
+                                            int                 on);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h b/src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h
new file mode 100644 (file)
index 0000000..cafd503
--- /dev/null
@@ -0,0 +1,285 @@
+#ifndef ECORE_COCOA_KEYS_H__
+#define ECORE_COCOA_KEYS_H__
+
+struct _ecore_cocoa_keys_s
+{
+   int         code;
+   const char  *name;
+   const char  *compose;
+};
+
+static const struct _ecore_cocoa_keys_s keystable[] =
+{
+
+{ 0,                         "0x00",         "" },
+{ 0,                         "First",        "" },
+{ 3,                         "Return",       "\015" },
+{ 8,                         "BackSpace",    "\010" },
+{ 9,                         "Tab",          "\011" },
+{ 12,                        "Clear",        "" },
+{ 13,                        "Return",       "\015" },
+{ 19,                        "Pause",        "" },
+{ 25,                        "BackTab",        ""},
+{ 27,                        "Escape",       "" },
+{ 32,                        "space",        " " },
+{ 33,                        "exclam",       "!" },
+{ 34,                        "quotedbl",     "\"" },
+{ 35,                        "numbersign",   "#" },
+{ 36,                        "dollar",       "$" },
+{ 37,                        "percent",      "%%" },
+{ 38,                        "ampersand",    "&" },
+{ 39,                        "apostrophe",   "'" },
+{ 40,                        "parenleft",    "(" },
+{ 41,                        "parenright",   ")" },
+{ 42,                        "asterik",      "*" },
+{ 43,                        "plus",         "+" },
+{ 44,                        "comma",        "," },
+{ 45,                        "minus",        "-" },
+{ 46,                        "period",       "." },
+{ 47,                        "slash",        "/" },
+{ 48,                        "0",            "0" },
+{ 49,                        "1",            "1" },
+{ 50,                        "2",            "2" },
+{ 51,                        "3",            "3" },
+{ 52,                        "4",            "4" },
+{ 53,                        "5",            "5" },
+{ 54,                        "6",            "6" },
+{ 55,                        "7",            "7" },
+{ 56,                        "8",            "8" },
+{ 57,                        "9",            "9" },
+{ 58,                        "colon",        ";" },
+{ 59,                        "semicolon",    ";" },
+{ 60,                        "less",         "<" },
+{ 61,                        "equal",        "=" },
+{ 62,                        "greater",      ">" },
+{ 63,                        "question",     "?" },
+{ 64,                        "at",           "@" },
+
+{ 91,                        "bracketleft",  "[" },
+{ 92,                        "backslash",    "\\" },
+{ 93,                        "bracketright", "]" },
+{ 94,                        "asciicircumm", "^" },
+{ 95,                        "underscore",   "_" },
+{ 96,                        "backquote",    "`" },
+{ 97,                        "a",            "a" },
+{ 98,                        "b",            "b" },
+{ 99,                        "c",            "c" },
+{ 100,                       "d",            "d" },
+{ 101,                       "e",            "e" },
+{ 102,                       "f",            "f" },
+{ 103,                       "g",            "g" },
+{ 104,                       "h",            "h" },
+{ 105,                       "i",            "i" },
+{ 106,                       "j",            "j" },
+{ 107,                       "k",            "k" },
+{ 108,                       "l",            "l" },
+{ 109,                       "m",            "m" },
+{ 110,                       "n",            "n" },
+{ 111,                       "o",            "o" },
+{ 112,                       "p",            "p" },
+{ 113,                       "q",            "q" },
+{ 114,                       "r",            "r" },
+{ 115,                       "s",            "s" },
+{ 116,                       "t",            "t" },
+{ 117,                       "u",            "u" },
+{ 118,                       "v",            "v" },
+{ 119,                       "w",            "w" },
+{ 120,                       "x",            "x" },
+{ 121,                       "y",            "y" },
+{ 122,                       "z",            "z" },
+{ 123,                       "braceleft",    "" },
+{ 124,                       "pipe",         "" },
+{ 125,                       "braceright",   "" },
+{ 127,                       "Delete",       "\177" },
+{ 126,                       "asciitilde",   "~" },
+
+{ 160,                       "w0",           "" }, 
+{ 161,                       "w1",           "" },
+{ 162,                       "w2",           "" },
+{ 163,                       "w3",           "" },
+{ 164,                       "w4",           "" },
+{ 165,                       "w5",           "" },
+{ 166,                       "w6",           "" },
+{ 167,                       "w7",           "" },
+{ 168,                       "w8",           "" },
+{ 169,                       "w9",           "" },
+{ 170,                       "w10",          "" },
+{ 171,                       "w11",          "" },
+{ 172,                       "w12",          "" },
+{ 173,                       "w13",          "" },
+{ 174,                       "w14",          "" },
+{ 175,                       "w15",          "" },
+{ 176,                       "w16",          "" },
+{ 177,                       "w17",          "" },
+{ 178,                       "w18",          "" },
+{ 179,                       "w19",          "" },
+{ 180,                       "w20",          "" },
+{ 181,                       "w21",          "" },
+{ 182,                       "w22",          "" },
+{ 183,                       "w23",          "" },
+{ 184,                       "w24",          "" },
+{ 185,                       "w25",          "" },
+{ 186,                       "w26",          "" },
+{ 187,                       "w27",          "" },
+{ 188,                       "w28",          "" },
+{ 189,                       "w29",          "" },
+{ 190,                       "w30",          "" },
+{ 191,                       "w31",          "" },
+{ 192,                       "w32",          "" },
+{ 193,                       "w33",          "" },
+{ 194,                       "w34",          "" },
+{ 195,                       "w35",          "" },
+{ 196,                       "w36",          "" },
+{ 197,                       "w37",          "" },
+{ 198,                       "w38",          "" },
+{ 199,                       "w39",          "" },
+{ 200,                       "w40",          "" },
+{ 201,                       "w41",          "" },
+{ 202,                       "w42",          "" },
+{ 203,                       "w43",          "" },
+{ 204,                       "w44",          "" },
+{ 205,                       "w45",          "" },
+{ 206,                       "w46",          "" },
+{ 207,                       "w47",          "" },
+{ 208,                       "w48",          "" },
+{ 209,                       "w49",          "" },
+{ 210,                       "w50",          "" },
+{ 211,                       "w51",          "" },
+{ 212,                       "w52",          "" },
+{ 213,                       "w53",          "" },
+{ 214,                       "w54",          "" },
+{ 215,                       "w55",          "" },
+{ 216,                       "w56",          "" },
+{ 217,                       "w57",          "" },
+{ 218,                       "w58",          "" },
+{ 219,                       "w59",          "" },
+{ 220,                       "w60",          "" },
+{ 221,                       "w61",          "" },
+{ 222,                       "w62",          "" },
+{ 223,                       "w63",          "" },
+{ 224,                       "w64",          "" },
+{ 225,                       "w65",          "" },
+{ 226,                       "w66",          "" },
+{ 227,                       "w67",          "" },
+{ 228,                       "w68",          "" },
+{ 229,                       "w69",          "" },
+{ 230,                       "w70",          "" },
+{ 231,                       "w71",          "" },
+{ 232,                       "w72",          "" },
+{ 233,                       "w73",          "" },
+{ 234,                       "w74",          "" },
+{ 235,                       "w75",          "" },
+{ 236,                       "w76",          "" },
+{ 237,                       "w77",          "" },
+{ 238,                       "w78",          "" },
+{ 239,                       "w79",          "" },
+{ 240,                       "w80",          "" },
+{ 241,                       "w81",          "" },
+{ 242,                       "w82",          "" },
+{ 243,                       "w83",          "" },
+{ 244,                       "w84",          "" },
+{ 245,                       "w85",          "" },
+{ 246,                       "w86",          "" },
+{ 247,                       "w87",          "" },
+{ 248,                       "w88",          "" },
+{ 249,                       "w89",          "" },
+{ 250,                       "w90",          "" },
+{ 251,                       "w91",          "" },
+{ 252,                       "w92",          "" },
+{ 253,                       "w93",          "" },
+{ 254,                       "w94",          "" },
+{ 255,                       "w95",          "" },
+
+{ 256,                       "KP0",          "0" },
+{ 257,                       "KP1",          "1" },
+{ 258,                       "KP2",          "2" },
+{ 259,                       "KP3",          "3" },
+{ 260,                       "KP4",          "4" },
+{ 261,                       "KP5",          "5" },
+{ 262,                       "KP6",          "6" },
+{ 263,                       "KP7",          "7" },
+{ 264,                       "KP8",          "8" },
+{ 265,                       "KP9",          "9" },
+{ 266,                       "period",       "." },
+{ 267,                       "KP_Divide",    "/" },
+{ 268,                       "KP_Multiply",  "*" },
+{ 269,                       "KP_Minus",     "-" },
+{ 270,                       "KP_Plus",      "+" },
+{ 271,                       "KP_Enter",     "\015" },
+{ 272,                       "KP_Equals",    "=" },
+
+{ NSUpArrowFunctionKey,      "Up",           "" },
+{ NSDownArrowFunctionKey,    "Down",         "" },
+{ NSRightArrowFunctionKey,   "Right",        "" },
+{ NSLeftArrowFunctionKey,    "Left",         "" },
+{ NSInsertFunctionKey,       "Insert",       "" },
+{ NSHomeFunctionKey,         "Home",         "" },
+{ NSEndFunctionKey,          "End",          "" },
+{ NSPageUpFunctionKey,       "Page_Up",      "" },
+{ NSPageDownFunctionKey,     "Page_Down",    "" },
+
+{ NSF1FunctionKey,           "F1",           "" },
+{ NSF2FunctionKey,           "F2",           "" },
+{ NSF3FunctionKey,           "F3",           "" },
+{ NSF4FunctionKey,           "F4",           "" },
+{ NSF5FunctionKey,           "F5",           "" },
+{ NSF6FunctionKey,           "F6",           "" },
+{ NSF7FunctionKey,           "F7",           "" },
+{ NSF8FunctionKey,           "F8",           "" },
+{ NSF9FunctionKey,           "F9",           "" },
+{ NSF10FunctionKey,          "F10",          "" },
+{ NSF11FunctionKey,          "F11",          "" },
+{ NSF12FunctionKey,          "F12",          "" },
+{ NSF13FunctionKey,          "F13",          "" },
+{ NSF14FunctionKey,          "F14",          "" },
+{ NSF15FunctionKey,          "F15",          "" },
+{ NSF16FunctionKey,          "F16",          "" },
+{ NSF17FunctionKey,          "F17",          "" },
+{ NSF18FunctionKey,          "F18",          "" },
+{ NSF19FunctionKey,          "F19",          "" },
+{ NSF20FunctionKey,          "F20",          "" },
+{ NSF21FunctionKey,          "F21",          "" },
+{ NSF22FunctionKey,          "F22",          "" },
+{ NSF23FunctionKey,          "F23",          "" },
+{ NSF24FunctionKey,          "F24",          "" },
+{ NSF25FunctionKey,          "F25",          "" },
+{ NSF26FunctionKey,          "F26",          "" },
+{ NSF27FunctionKey,          "F27",          "" },
+{ NSF28FunctionKey,          "F28",          "" },
+{ NSF29FunctionKey,          "F29",          "" },
+{ NSF30FunctionKey,          "F30",          "" },
+{ NSF31FunctionKey,          "F31",          "" },
+{ NSF32FunctionKey,          "F32",          "" },
+{ NSF33FunctionKey,          "F33",          "" },
+{ NSF34FunctionKey,          "F34",          "" },
+{ NSF35FunctionKey,          "F35",          "" },
+
+{ NSClearLineFunctionKey,    "Num_Lock",     "" },
+{ 301,                       "Caps_Lock",    "" },
+{ NSScrollLockFunctionKey,   "Scroll_Lock",  "" },
+{ 303,                       "Shift_R",      "" },
+{ 304,                       "Shift_L",      "" },
+{ 305,                       "Control_R",    "" },
+{ 306,                       "Control_L",    "" },
+{ 307,                       "Alt_R",        "" },
+{ 308,                       "Alt_L",        "" },
+{ 309,                       "Meta_R",       "" },
+{ 310,                       "Meta_L",       "" },
+{ 311,                       "Super_L",      "" },
+{ 312,                       "Super_R",      "" },
+
+{ NSModeSwitchFunctionKey,   "Mode",         "" },
+{ 314,                       "Compose",      "" },
+
+{ NSHelpFunctionKey,         "Help",         "" },
+{ NSPrintFunctionKey,        "Print",        "" },
+{ NSSysReqFunctionKey,       "SysReq",       "" },
+{ NSBreakFunctionKey,        "Break",        "" },
+{ NSMenuFunctionKey,         "Menu",         "" },
+{ 320,                       "Power",        "" },
+{ 321,                       "Euro",         "" },
+{ NSUndoFunctionKey,         "Undo",         "" }
+
+};
+
+#endif  /* ECORE_COCOA_KEYS_H__ */
diff --git a/src/lib/ecore_cocoa/Makefile.am b/src/lib/ecore_cocoa/Makefile.am
new file mode 100644 (file)
index 0000000..190d0fa
--- /dev/null
@@ -0,0 +1,32 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_input \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+if BUILD_ECORE_COCOA
+
+lib_LTLIBRARIES = libecore_cocoa.la
+include_HEADERS = \
+Ecore_Cocoa.h \
+Ecore_Cocoa_Keys.h
+
+libecore_cocoa_la_SOURCES = \
+ecore_cocoa.m \
+ecore_cocoa_window.m
+
+libecore_cocoa_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@
+
+libecore_cocoa_la_LDFLAGS = @cocoa_ldflags@ -version-info @version_info@ @ecore_cocoa_release_info@
+
+endif
+
+EXTRA_DIST = ecore_cocoa_private.h
diff --git a/src/lib/ecore_cocoa/ecore_cocoa.m b/src/lib/ecore_cocoa/ecore_cocoa.m
new file mode 100644 (file)
index 0000000..ad2e767
--- /dev/null
@@ -0,0 +1,280 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Cocoa/Cocoa.h>
+
+#include <Eina.h>
+
+#include <Ecore.h>
+#include <ecore_private.h>
+#include <Ecore_Input.h>
+
+#include "Ecore_Cocoa.h"
+#include "Ecore_Cocoa_Keys.h"
+
+EAPI int ECORE_COCOA_EVENT_GOT_FOCUS = 0;
+EAPI int ECORE_COCOA_EVENT_LOST_FOCUS = 0;
+EAPI int ECORE_COCOA_EVENT_RESIZE = 0;
+EAPI int ECORE_COCOA_EVENT_EXPOSE = 0;
+
+static int _ecore_cocoa_init_count = 0;
+
+static int old_flags;
+
+EAPI int
+ecore_cocoa_init(const char *name __UNUSED__)
+{
+   if (++_ecore_cocoa_init_count != 1)
+     return _ecore_cocoa_init_count;
+
+   if (!ecore_event_init())
+     return --_ecore_cocoa_init_count;
+
+   ECORE_COCOA_EVENT_GOT_FOCUS  = ecore_event_type_new();
+   ECORE_COCOA_EVENT_LOST_FOCUS = ecore_event_type_new();
+   ECORE_COCOA_EVENT_RESIZE     = ecore_event_type_new();
+   ECORE_COCOA_EVENT_EXPOSE     = ecore_event_type_new();
+
+   return _ecore_cocoa_init_count;
+}
+
+/**
+ * Shuts down the Ecore_Cocoa library.
+ * @return  @c The number of times the system has been initialised without
+ *             being shut down.
+ * @ingroup Ecore_Cocoa_Library_Group
+ */
+EAPI int
+ecore_cocoa_shutdown(void)
+{
+   if (--_ecore_cocoa_init_count != 0)
+     return _ecore_cocoa_init_count;
+
+   ecore_event_shutdown();
+
+   return _ecore_cocoa_init_count;
+}
+
+EAPI void
+ecore_cocoa_feed_events(void)
+{
+   NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.001];
+   NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                       untilDate:date
+                                          inMode:NSDefaultRunLoopMode
+                                         dequeue:YES];
+   [date release];
+   if (!event) return; // SDL loops until null; maybe we should do that too. or not.
+
+   unsigned int time = (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff);
+
+   switch([event type])
+   {
+      case NSMouseMoved:
+      case NSLeftMouseDragged:
+      case NSRightMouseDragged:
+      case NSOtherMouseDragged:
+      {
+         Ecore_Event_Mouse_Move * ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
+         if (!ev) return;
+         ev->x = [event locationInWindow].x;
+         ev->y = [event locationInWindow].y;
+         ev->root.x = ev->x;
+         ev->root.y = ev->y;
+         ev->timestamp = time;
+         ev->window = [event window];
+         ev->modifiers = 0; /* FIXME: keep modifier around. */
+
+         ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+
+         [NSApp sendEvent:event]; // pass along mouse events, for window manager
+         break;
+      }
+      case NSLeftMouseDown:
+      case NSRightMouseDown:
+      case NSOtherMouseDown:
+      {
+         Ecore_Event_Mouse_Button * ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
+         if (!ev) return;
+         ev->x = [event locationInWindow].x;
+         ev->y = [event locationInWindow].y;
+         ev->root.x = ev->x;
+         ev->root.y = ev->y;
+         ev->timestamp = time;
+         ev->buttons = [event buttonNumber] + 1; // Apple indexes buttons from 0
+
+         if ([event clickCount] == 2)
+            ev->double_click = 1;
+         else
+            ev->double_click = 0;
+
+         if ([event clickCount] >= 3)
+            ev->triple_click = 1;
+         else
+            ev->triple_click = 0;
+
+         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
+
+         [NSApp sendEvent:event]; // pass along mouse events, for window manager
+         break;
+      }
+      case NSLeftMouseUp:
+      case NSRightMouseUp:
+      case NSOtherMouseUp:
+      {
+         Ecore_Event_Mouse_Button * ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
+         if (!ev) return;
+         ev->x = [event locationInWindow].x;
+         ev->y = [event locationInWindow].y;
+         ev->root.x = ev->x;
+         ev->root.y = ev->y;
+         ev->timestamp = time;
+         ev->buttons = [event buttonNumber] + 1; // Apple indexes buttons from 0
+
+         if ([event clickCount] == 2)
+            ev->double_click = 1;
+         else
+            ev->double_click = 0;
+
+         if ([event clickCount] >= 3)
+            ev->triple_click = 1;
+         else
+            ev->triple_click = 0;
+
+         ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
+
+         [NSApp sendEvent:event]; // pass along mouse events, for window manager
+         break;
+      }
+      case NSKeyDown:
+      {
+         Ecore_Event_Key *ev;
+         unsigned int     i;
+
+         ev = calloc(1, sizeof (Ecore_Event_Key));
+         if (!ev) return;
+         ev->timestamp = time;
+
+         for (i = 0; i < sizeof (keystable) / sizeof (struct _ecore_cocoa_keys_s); ++i)
+         {
+            if (keystable[i].code == tolower([[event charactersIgnoringModifiers] characterAtIndex:0]))
+            {
+               ev->keyname = keystable[i].name;
+               ev->string = keystable[i].compose;
+
+               ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
+               return;
+            }
+         }
+
+         break;
+      }
+      case NSKeyUp:
+      {
+         Ecore_Event_Key *ev;
+         unsigned int     i;
+
+         ev = calloc(1, sizeof (Ecore_Event_Key));
+         if (!ev) return;
+         ev->timestamp = time;
+
+         for (i = 0; i < sizeof (keystable) / sizeof (struct _ecore_cocoa_keys_s); ++i)
+         {
+            if (keystable[i].code == tolower([[event charactersIgnoringModifiers] characterAtIndex:0]))
+            {
+               ev->keyname = keystable[i].name;
+               ev->string = keystable[i].compose;
+
+               ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
+               return;
+            }
+         }
+
+         break;
+      }
+      case NSFlagsChanged:
+      {
+         int flags = [event modifierFlags];
+
+         Ecore_Event_Key *evDown = NULL;
+         Ecore_Event_Key *evUp = NULL;
+
+         evDown = calloc(1, sizeof (Ecore_Event_Key));
+         if (!evDown) return;
+
+         evUp = calloc(1, sizeof (Ecore_Event_Key));
+         if (!evUp)
+           {
+              free(evDown);
+              return;
+           }
+
+         // Turn special key flags on
+         if (flags & NSShiftKeyMask)
+            evDown->keyname = "Shift_L";
+         else if (flags & NSControlKeyMask)
+            evDown->keyname = "Control_L";
+         else if (flags & NSAlternateKeyMask)
+            evDown->keyname = "Alt_L";
+         else if (flags & NSCommandKeyMask)
+            evDown->keyname = "Super_L";
+         else if (flags & NSAlphaShiftKeyMask)
+            evDown->keyname = "Caps_Lock";
+
+         if (evDown->keyname)
+         {
+            evDown->timestamp = time;
+            evDown->string = "";
+            ecore_event_add(ECORE_EVENT_KEY_DOWN, evDown, NULL, NULL);
+            old_flags = flags;
+            break;
+         }
+
+         int changed_flags = flags ^ old_flags;
+
+         // Turn special key flags off
+         if (changed_flags & NSShiftKeyMask)
+            evUp->keyname = "Shift_L";
+         else if (changed_flags & NSControlKeyMask)
+            evUp->keyname = "Control_L";
+         else if (changed_flags & NSAlternateKeyMask)
+            evUp->keyname = "Alt_L";
+         else if (changed_flags & NSCommandKeyMask)
+            evUp->keyname = "Super_L";
+         else if (changed_flags & NSAlphaShiftKeyMask)
+            evUp->keyname = "Caps_Lock";
+
+         if (evUp->keyname)
+         {
+            evUp->timestamp = time;
+            evUp->string = "";
+            ecore_event_add(ECORE_EVENT_KEY_UP, evUp, NULL, NULL);
+            old_flags = flags;
+            break;
+         }
+
+         break;
+      }
+      case NSAppKitDefined:
+      {
+         if ([event subtype] == NSApplicationActivatedEventType)
+            ecore_event_add(ECORE_COCOA_EVENT_GOT_FOCUS, NULL, NULL, NULL);
+         else if ([event subtype] == NSApplicationDeactivatedEventType)
+            ecore_event_add(ECORE_COCOA_EVENT_LOST_FOCUS, NULL, NULL, NULL);
+         [NSApp sendEvent:event]; // pass along AppKit events, for window manager
+         break;
+      }
+      case NSScrollWheel:
+      {
+         break;
+      }
+      default:
+      {
+         [NSApp sendEvent:event];
+         break;
+      }
+   }
+
+   [event release];
+}
diff --git a/src/lib/ecore_cocoa/ecore_cocoa_private.h b/src/lib/ecore_cocoa/ecore_cocoa_private.h
new file mode 100644 (file)
index 0000000..05bdc1f
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _ECORE_COCOA_PRIVATE_H\r
+#define _ECORE_COCOA_PRIVATE_H\r
+\r
+\r
+struct _Ecore_Cocoa_Window\r
+{\r
+   NSWindow *window;\r
+\r
+   unsigned int borderless : 1;\r
+};\r
+\r
+\r
+#endif\r
diff --git a/src/lib/ecore_cocoa/ecore_cocoa_window.m b/src/lib/ecore_cocoa/ecore_cocoa_window.m
new file mode 100644 (file)
index 0000000..751bde4
--- /dev/null
@@ -0,0 +1,110 @@
+#ifdef HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif\r
+\r
+#include <Cocoa/Cocoa.h>\r
+\r
+#include "Ecore_Cocoa.h"\r
+\r
+Ecore_Cocoa_Window *\r
+ecore_cocoa_window_new(int x,\r
+                      int y,\r
+                      int width,\r
+                      int height)\r
+{\r
+  NSWindow *window;\r
+\r
+  window = [[NSWindow alloc]\r
+            initWithContentRect:NSMakeRect(x, y, width, height)\r
+            styleMask:(NSTitledWindowMask |\r
+                       NSClosableWindowMask |\r
+                       NSResizableWindowMask |\r
+                       NSMiniaturizableWindowMask)\r
+            backing:NSBackingStoreBuffered\r
+            defer:NO\r
+            screen:nil\r
+           ];\r
+  if (!window)\r
+    return NULL;\r
+\r
+  return window;\r
+}\r
+\r
+void\r
+ecore_cocoa_window_free(Ecore_Cocoa_Window *window)\r
+{\r
+  if (!window)\r
+    return;\r
+\r
+  [window release];\r
+}\r
+\r
+void\r
+ecore_cocoa_window_move(Ecore_Cocoa_Window *window,\r
+                       int                 x,\r
+                       int                 y)\r
+{\r
+  if (!window)\r
+    return;\r
+}\r
+\r
+void\r
+ecore_cocoa_window_resize(Ecore_Cocoa_Window *window,\r
+                         int                 width,\r
+                         int                 height)\r
+{\r
+  if (!window)\r
+    return;\r
+\r
+  [window setContentSize: NSMakeSize(width, height)];\r
+}\r
+\r
+void\r
+ecore_cocoa_window_move_resize(Ecore_Cocoa_Window *window,\r
+                              int                 x,\r
+                              int                 y,\r
+                              int                 width,\r
+                              int                 height)\r
+{\r
+  if (!window)\r
+    return;\r
+}\r
+\r
+void\r
+ecore_cocoa_window_title_set(Ecore_Cocoa_Window *window, const char *title)\r
+{\r
+  if (!window || !title)\r
+    return;\r
+\r
+  [window setTitle:[NSString stringWithUTF8String:title]];\r
+}\r
+\r
+void\r
+ecore_cocoa_window_show(Ecore_Cocoa_Window *window)\r
+{\r
+  if (!window || [window isVisible])\r
+    return;\r
+\r
+  [window orderFront:NSApp];\r
+}\r
+\r
+void\r
+ecore_cocoa_window_hide(Ecore_Cocoa_Window *window)\r
+{\r
+  if (!window || ![window isVisible])\r
+    return;\r
+\r
+  [window orderOut:NSApp];\r
+}\r
+\r
+void\r
+ecore_cocoa_window_borderless_set(Ecore_Cocoa_Window *window,\r
+                                  int                 on)\r
+{\r
+  if (!window)\r
+    return;\r
+\r
+  if (on)\r
+    [window setContentBorderThickness:0.0\r
+           forEdje:NSMinXEdge | NSMinYEdge | NSMaxXEdge | NSMaxYEdge];\r
+}\r
diff --git a/src/lib/ecore_con/.cvsignore b/src/lib/ecore_con/.cvsignore
new file mode 100644 (file)
index 0000000..310b663
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+Ecore_Con.h
+Makefile
+Makefile.in
+*.lo
+libecore_con.la
diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h
new file mode 100644 (file)
index 0000000..7061f9f
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#ifndef _ECORE_CON_H
+#define _ECORE_CON_H
+
+#include <time.h>
+#include <libgen.h>
+#ifdef _WIN32
+# include <ws2tcpip.h>
+#else
+# include <netdb.h>
+#endif
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+/**
+ * @file Ecore_Con.h
+ * @brief Sockets functions.
+ *
+ * The Ecore Connection Library ( @c Ecore_Con ) provides simple mechanisms
+ * for communications between programs using reliable sockets.  It saves
+ * the programmer from having to worry about file descripters and waiting
+ * for incoming connections.
+ *
+ * There are two main objects in the @c Ecore_Con library: the @c
+ * Ecore_Con_Server and the @c Ecore_Con_Client.
+ *
+ * The @c Ecore_Con_Server represents a server that can be connected to.
+ * It is used regardless of whether the program is acting as a server or
+ * client itself.
+ *
+ * To create a listening server, call @c ecore_con_server_add().
+ *
+ * To connect to a server, call @c ecore_con_server_connect().  Data can
+ * then be sent to the server using the @c ecore_con_server_send().
+ *
+ * Whenever a client connection is made to an @c Ecore_Con_Server, a
+ * @c ECORE_CON_CLIENT_ADD event is emitted.  Any event callbacks that are
+ * called receive a @c Ecore_Con_Client object, which represents a
+ * connection that that particular client.
+ *
+ * Functions are described in the following groupings:
+ * @li @ref Ecore_Con_Lib_Group
+ * @li @ref Ecore_Con_Server_Group
+ * @li @ref Ecore_Con_Client_Group
+ * @li @ref Ecore_Con_Url_Group
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   typedef struct _Ecore_Con_Server  Ecore_Con_Server; /**< A connection handle */
+   typedef struct _Ecore_Con_Client  Ecore_Con_Client; /**< A connection handle */
+   typedef struct _Ecore_Con_Url     Ecore_Con_Url;
+   typedef struct _Ecore_Con_Info    Ecore_Con_Info;
+
+   typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
+
+   typedef enum _Ecore_Con_Type
+     {
+       ECORE_CON_LOCAL_USER       = 0,
+       ECORE_CON_LOCAL_SYSTEM     = 1,
+       ECORE_CON_LOCAL_ABSTRACT   = 2,
+       ECORE_CON_REMOTE_TCP       = 3,
+       ECORE_CON_REMOTE_MCAST     = 4,
+       ECORE_CON_REMOTE_UDP       = 5,
+       ECORE_CON_REMOTE_BROADCAST = 6,
+       ECORE_CON_REMOTE_NODELAY   = 7,
+          
+       ECORE_CON_USE_SSL2 = (1 << 4),
+       ECORE_CON_USE_SSL3 = (1 << 5),
+       ECORE_CON_USE_TLS  = (1 << 6)
+     } Ecore_Con_Type;
+#define ECORE_CON_USE_SSL ECORE_CON_USE_SSL2
+#define ECORE_CON_REMOTE_SYSTEM ECORE_CON_REMOTE_TCP
+
+   typedef enum _Ecore_Con_Url_Time
+     {
+       ECORE_CON_URL_TIME_NONE = 0,
+       ECORE_CON_URL_TIME_IFMODSINCE,
+       ECORE_CON_URL_TIME_IFUNMODSINCE,
+       ECORE_CON_URL_TIME_LASTMOD
+     } Ecore_Con_Url_Time;
+
+   typedef struct _Ecore_Con_Event_Client_Add  Ecore_Con_Event_Client_Add;
+   typedef struct _Ecore_Con_Event_Client_Del  Ecore_Con_Event_Client_Del;
+   typedef struct _Ecore_Con_Event_Server_Add  Ecore_Con_Event_Server_Add;
+   typedef struct _Ecore_Con_Event_Server_Del  Ecore_Con_Event_Server_Del;
+   typedef struct _Ecore_Con_Event_Client_Data Ecore_Con_Event_Client_Data;
+   typedef struct _Ecore_Con_Event_Server_Data Ecore_Con_Event_Server_Data;
+   typedef struct _Ecore_Con_Event_Url_Data Ecore_Con_Event_Url_Data;
+   typedef struct _Ecore_Con_Event_Url_Complete Ecore_Con_Event_Url_Complete;
+   typedef struct _Ecore_Con_Event_Url_Progress Ecore_Con_Event_Url_Progress;
+
+   struct _Ecore_Con_Event_Client_Add
+     {
+       Ecore_Con_Client *client;
+     };
+
+   struct _Ecore_Con_Event_Client_Del
+     {
+       Ecore_Con_Client *client;
+     };
+
+   struct _Ecore_Con_Event_Server_Add
+     {
+       Ecore_Con_Server *server;
+     };
+
+   struct _Ecore_Con_Event_Server_Del
+     {
+       Ecore_Con_Server *server;
+     };
+
+   struct _Ecore_Con_Event_Client_Data
+     {
+       Ecore_Con_Client *client;
+       void             *data;
+       int               size;
+     };
+
+   struct _Ecore_Con_Event_Server_Data
+     {
+       Ecore_Con_Server *server;
+       void             *data;
+       int               size;
+     };
+
+   struct _Ecore_Con_Event_Url_Data
+     {
+       Ecore_Con_Url    *url_con;
+       int               size;
+       unsigned char     data[1];
+     };
+
+   struct _Ecore_Con_Event_Url_Complete
+     {
+       Ecore_Con_Url    *url_con;
+       int               status;
+     };
+
+   struct _Ecore_Con_Event_Url_Progress
+     {
+       Ecore_Con_Url    *url_con;
+       struct {
+          double         total;
+          double         now;
+       } down;
+       struct {
+          double         total;
+          double         now;
+       } up;
+     };
+
+   EAPI extern int ECORE_CON_EVENT_CLIENT_ADD;
+   EAPI extern int ECORE_CON_EVENT_CLIENT_DEL;
+   EAPI extern int ECORE_CON_EVENT_SERVER_ADD;
+   EAPI extern int ECORE_CON_EVENT_SERVER_DEL;
+   EAPI extern int ECORE_CON_EVENT_CLIENT_DATA;
+   EAPI extern int ECORE_CON_EVENT_SERVER_DATA;
+   EAPI extern int ECORE_CON_EVENT_URL_DATA;
+   EAPI extern int ECORE_CON_EVENT_URL_COMPLETE;
+   EAPI extern int ECORE_CON_EVENT_URL_PROGRESS;
+
+   EAPI int               ecore_con_init(void);
+   EAPI int               ecore_con_shutdown(void);
+
+   EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, const char *name, int port, const void *data);
+
+   EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type, const char *name, int port, const void *data);
+   EAPI void             *ecore_con_server_del(Ecore_Con_Server *svr);
+   EAPI void             *ecore_con_server_data_get(Ecore_Con_Server *svr);
+   EAPI int               ecore_con_server_connected_get(Ecore_Con_Server *svr);
+   EAPI Eina_List       *ecore_con_server_clients_get(Ecore_Con_Server *svr);
+   EAPI int               ecore_con_server_send(Ecore_Con_Server *svr, const void *data, int size);
+   EAPI void              ecore_con_server_client_limit_set(Ecore_Con_Server *svr, int client_limit, char reject_excess_clients);
+   EAPI char             *ecore_con_server_ip_get(Ecore_Con_Server *svr);
+   EAPI void              ecore_con_server_flush(Ecore_Con_Server *svr);
+
+   EAPI int               ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size);
+   EAPI Ecore_Con_Server *ecore_con_client_server_get(Ecore_Con_Client *cl);
+   EAPI void             *ecore_con_client_del(Ecore_Con_Client *cl);
+   EAPI void              ecore_con_client_data_set(Ecore_Con_Client *cl, const void *data);
+   EAPI void             *ecore_con_client_data_get(Ecore_Con_Client *cl);
+   EAPI char             *ecore_con_client_ip_get(Ecore_Con_Client *cl);
+   EAPI void              ecore_con_client_flush(Ecore_Con_Client *cl);
+
+   EAPI int               ecore_con_ssl_available_get(void);
+
+   EAPI int               ecore_con_url_init(void);
+   EAPI int               ecore_con_url_shutdown(void);
+   EAPI Ecore_Con_Url    *ecore_con_url_new(const char *url);
+   EAPI Ecore_Con_Url    *ecore_con_url_custom_new(const char *url, const char *custom_request);
+   EAPI void              ecore_con_url_destroy(Ecore_Con_Url *url_con);
+   EAPI void              ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data);
+   EAPI void             *ecore_con_url_data_get(Ecore_Con_Url *url_con);
+   EAPI void              ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, const char *key, const char *value);
+   EAPI void              ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con);
+   EAPI const Eina_List  *ecore_con_url_response_headers_get(Ecore_Con_Url *url_con);
+   EAPI int               ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url);
+   EAPI void             ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd);
+   EAPI int              ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con);
+   EAPI int              ecore_con_url_httpauth_set(Ecore_Con_Url *url_con, const char *username, const char *password, Eina_Bool safe);
+   EAPI int               ecore_con_url_send(Ecore_Con_Url *url_con, const void *data, size_t length, const char *content_type);
+   EAPI void              ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t tm);
+
+   EAPI int              ecore_con_info_get(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data, struct addrinfo *hints);
+
+   EAPI int              ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, const char *filename, const char *user, const char *pass, const char *upload_dir);
+   EAPI void             ecore_con_url_verbose_set(Ecore_Con_Url *url_con, int verbose);
+   EAPI void             ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, int use_epsv);
+   EAPI int               ecore_con_url_http_post_send(Ecore_Con_Url *url_con, void *curl_httppost);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_con/Makefile.am b/src/lib/ecore_con/Makefile.am
new file mode 100644 (file)
index 0000000..a4ba20b
--- /dev/null
@@ -0,0 +1,42 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_con \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_con \
+@SSL_CFLAGS@ \
+@CURL_CFLAGS@ \
+@EINA_CFLAGS@ \
+@TLS_CFLAGS@ \
+@CARES_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+if BUILD_ECORE_CON
+
+lib_LTLIBRARIES = libecore_con.la
+include_HEADERS = \
+Ecore_Con.h
+
+libecore_con_la_SOURCES = \
+ecore_con.c \
+ecore_con_ssl.c \
+ecore_con_url.c \
+ecore_con_local.c
+
+if HAVE_CARES
+libecore_con_la_SOURCES += ecore_con_ares.c
+else
+libecore_con_la_SOURCES += ecore_con_info.c
+endif
+
+libecore_con_la_CFLAGS = @WIN32_CFLAGS@
+libecore_con_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @TLS_LIBS@ @CARES_LIBS@ @WIN32_LIBS@
+
+libecore_con_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_con_release_info@
+
+endif
+
+EXTRA_DIST = ecore_con_private.h
diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
new file mode 100644 (file)
index 0000000..5a912e8
--- /dev/null
@@ -0,0 +1,1698 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+static void _ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *info);
+
+static void _ecore_con_server_free(Ecore_Con_Server *svr);
+static void _ecore_con_client_free(Ecore_Con_Client *cl);
+
+static int _ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
+static void _ecore_con_server_flush(Ecore_Con_Server *svr);
+static void _ecore_con_client_flush(Ecore_Con_Client *cl);
+
+static void _ecore_con_event_client_add_free(void *data, void *ev);
+static void _ecore_con_event_client_del_free(void *data, void *ev);
+static void _ecore_con_event_client_data_free(void *data, void *ev);
+static void _ecore_con_event_server_add_free(void *data, void *ev);
+static void _ecore_con_event_server_del_free(void *data, void *ev);
+static void _ecore_con_event_server_data_free(void *data, void *ev);
+
+EAPI int ECORE_CON_EVENT_CLIENT_ADD = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_DEL = 0;
+EAPI int ECORE_CON_EVENT_SERVER_ADD = 0;
+EAPI int ECORE_CON_EVENT_SERVER_DEL = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_DATA = 0;
+EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
+
+static Eina_List *servers = NULL;
+static int _ecore_con_init_count = 0;
+int _ecore_con_log_dom = -1;
+
+/**
+ * @defgroup Ecore_Con_Lib_Group Ecore Connection Library Functions
+ *
+ * Utility functions that set up and shut down the Ecore Connection
+ * library.
+ */
+
+/**
+ * Initialises the Ecore_Con library.
+ * @return  Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_Con_Lib_Group
+ */
+EAPI int
+ecore_con_init(void)
+{
+   if (++_ecore_con_init_count != 1)
+     return _ecore_con_init_count;
+
+#ifdef HAVE_EVIL
+   if (!evil_init())
+     return --_ecore_con_init_count;
+#endif
+
+   if (!ecore_init())
+     return --_ecore_con_init_count;
+
+   _ecore_con_log_dom = eina_log_domain_register("EcoreCon", ECORE_CON_DEFAULT_LOG_COLOR);
+   if(_ecore_con_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for Ecore Con.");
+       ecore_shutdown();
+       return --_ecore_con_init_count;
+     }
+   ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new();
+   ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new();
+   ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new();
+   ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new();
+   ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new();
+   ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
+
+   /* TODO Remember return value, if it fails, use gethostbyname() */
+   ecore_con_ssl_init();
+   ecore_con_info_init();
+
+   return _ecore_con_init_count;
+}
+
+/**
+ * Shuts down the Ecore_Con library.
+ * @return  Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_Con_Lib_Group
+ */
+EAPI int
+ecore_con_shutdown(void)
+{
+   if (--_ecore_con_init_count != 0)
+     return _ecore_con_init_count;
+
+   while (servers)
+     _ecore_con_server_free(eina_list_data_get(servers));
+
+   ecore_con_info_shutdown();
+   ecore_con_ssl_shutdown();
+   eina_log_domain_unregister(_ecore_con_log_dom);
+   _ecore_con_log_dom = -1;
+   ecore_shutdown();
+#ifdef HAVE_EVIL
+   evil_shutdown();
+#endif
+
+   return _ecore_con_init_count;
+}
+
+/**
+ * @defgroup Ecore_Con_Server_Group Ecore Connection Server Functions
+ *
+ * Functions that operate on Ecore server objects.
+ */
+
+/**
+ * Creates a server to listen for connections.
+ *
+ * The socket on which the server listens depends on the connection
+ * type:
+ * @li If @a compl_type is @c ECORE_CON_LOCAL_USER, the server will listen on
+ *     the Unix socket "~/.ecore/[name]/[port]".
+ * @li If @a compl_type is @c ECORE_CON_LOCAL_SYSTEM, the server will listen
+ *     on Unix socket "/tmp/.ecore_service|[name]|[port]".
+ * @li If @a compl_type is @c ECORE_CON_REMOTE_TCP, the server will listen
+ *     on TCP port @c port.
+ *
+ * @param  compl_type The connection type.
+ * @param  name       Name to associate with the socket.  It is used when
+ *                    generating the socket name of a Unix socket.  Though
+ *                    it is not used for the TCP socket, it still needs to
+ *                    be a valid character array.  @c NULL will not be
+ *                    accepted.
+ * @param  port       Number to identify socket.  When a Unix socket is used,
+ *                    it becomes part of the socket name.  When a TCP socket
+ *                    is used, it is used as the TCP port.
+ * @param  data       Data to associate with the created Ecore_Con_Server
+ *                    object.
+ * @return A new Ecore_Con_Server.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI Ecore_Con_Server *
+ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
+                    const void *data)
+{
+   Ecore_Con_Server   *svr;
+   Ecore_Con_Type      type;
+
+   if (port < 0 || !name) return NULL;
+   /* local  user   socket: FILE:   ~/.ecore/[name]/[port] */
+   /* local  system socket: FILE:   /tmp/.ecore_service|[name]|[port] */
+   /* remote system socket: TCP/IP: [name]:[port] */
+   svr = calloc(1, sizeof(Ecore_Con_Server));
+   if (!svr) return NULL;
+
+   svr->name = strdup(name);
+   if (!svr->name) goto error;
+   svr->type = compl_type;
+   svr->port = port;
+   svr->data = (void *)data;
+   svr->created = 1;
+   svr->reject_excess_clients = 0;
+   svr->client_limit = -1;
+   svr->clients = NULL;
+   svr->ppid = getpid();
+   ecore_con_ssl_server_prepare(svr);
+
+   type = compl_type & ECORE_CON_TYPE;
+
+   if ((type == ECORE_CON_LOCAL_USER) || 
+       (type == ECORE_CON_LOCAL_SYSTEM) ||
+       (type == ECORE_CON_LOCAL_ABSTRACT))
+     {
+        /* Local */
+        if (!ecore_con_local_listen(svr, _ecore_con_svr_handler, svr)) goto error;
+     }
+   
+   if ((type == ECORE_CON_REMOTE_TCP) || 
+       (type == ECORE_CON_REMOTE_NODELAY))
+     {
+        /* TCP */
+        if (!ecore_con_info_tcp_listen(svr, _ecore_con_cb_tcp_listen, svr)) goto error;
+     }
+   else if ((type == ECORE_CON_REMOTE_MCAST) ||
+            (type == ECORE_CON_REMOTE_UDP))
+     {
+        /* UDP and MCAST */
+        if (!ecore_con_info_udp_listen(svr, _ecore_con_cb_udp_listen, svr)) goto error;
+     }
+   
+   servers = eina_list_append(servers, svr);
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
+   return svr;
+
+   error:
+   if (svr->name) free(svr->name);
+   if (svr->path) free(svr->path);
+#ifndef _WIN32
+   if (svr->fd >= 0) close(svr->fd);
+   if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
+   if (svr->write_buf) free(svr->write_buf);
+   if (svr->ip) free(svr->ip);
+#endif
+   ecore_con_ssl_server_shutdown(svr);
+   free(svr);
+   return NULL;
+}
+
+/**
+ * Creates a server object to represent the server listening at the
+ * given port.
+ *
+ * The socket to which the server connects depends on the connection type:
+ * @li If @a compl_type is @c ECORE_CON_LOCAL_USER, the function will
+ *     connect to the server listening on the Unix socket
+ *     "~/.ecore/[name]/[port]".
+ * @li If @a compl_type is @c ECORE_CON_LOCAL_SYSTEM, the function will
+ *     connect to the server listening on the Unix socket
+ *     "/tmp/.ecore_service|[name]|[port]".
+ * @li If @a compl_type is @c ECORE_CON_REMOTE_TCP, the function will
+ *     connect to the server listening on the TCP port "[name]:[port]".
+ *
+ * @param  compl_type The connection type.
+ * @param  name       Name used when determining what socket to connect to.
+ *                    It is used to generate the socket name when the socket
+ *                    is a Unix socket.  It is used as the hostname when
+ *                    connecting with a TCP socket.
+ * @param  port       Number to identify the socket to connect to.  Used when
+ *                    generating the socket name for a Unix socket, or as the
+ *                    TCP port when connecting to a TCP socket.
+ * @param  data       Data to associate with the created Ecore_Con_Server
+ *                    object.
+ * @return A new Ecore_Con_Server.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI Ecore_Con_Server *
+ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
+                        const void *data)
+{
+   Ecore_Con_Server   *svr;
+   Ecore_Con_Type      type;
+
+   if (!name) return NULL;
+   /* local  user   socket: FILE:   ~/.ecore/[name]/[port] */
+   /* local  system socket: FILE:   /tmp/.ecore_service|[name]|[port] */
+   /* remote system socket: TCP/IP: [name]:[port] */
+   svr = calloc(1, sizeof(Ecore_Con_Server));
+   if (!svr) return NULL;
+
+   svr->name = strdup(name);
+   if (!svr->name) goto error;
+   svr->type = compl_type;
+   svr->port = port;
+   svr->data = (void *)data;
+   svr->created = 0;
+   svr->reject_excess_clients = 0;
+   svr->clients = NULL;
+   svr->client_limit = -1;
+   ecore_con_ssl_server_prepare(svr);
+
+   type = compl_type & ECORE_CON_TYPE;
+
+   if (((type == ECORE_CON_REMOTE_TCP) || 
+        (type == ECORE_CON_REMOTE_NODELAY) ||
+       (type == ECORE_CON_REMOTE_UDP) || 
+        (type == ECORE_CON_REMOTE_BROADCAST)) &&
+       (port < 0))
+     goto error;
+   
+   if ((type == ECORE_CON_LOCAL_USER) || 
+       (type == ECORE_CON_LOCAL_SYSTEM) ||
+       (type == ECORE_CON_LOCAL_ABSTRACT))
+     {
+        /* Local */
+       if (!ecore_con_local_connect(svr, _ecore_con_cl_handler, svr, _ecore_con_event_server_add_free)) goto error;
+     }
+
+   if ((type == ECORE_CON_REMOTE_TCP) || 
+       (type == ECORE_CON_REMOTE_NODELAY))
+     {
+        /* TCP */
+        if (!ecore_con_info_tcp_connect(svr, _ecore_con_cb_tcp_connect, svr)) goto error;
+     }
+   else if ((type == ECORE_CON_REMOTE_UDP) || 
+            (type == ECORE_CON_REMOTE_BROADCAST))
+     {
+        /* UDP and MCAST */
+        if (!ecore_con_info_udp_connect(svr, _ecore_con_cb_udp_connect, svr)) goto error;
+     }
+
+   servers = eina_list_append(servers, svr);
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
+   return svr;
+
+   error:
+   if (svr->name) free(svr->name);
+   if (svr->path) free(svr->path);
+   if (svr->fd >= 0) close(svr->fd);
+   if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
+   ecore_con_ssl_server_shutdown(svr);
+   free(svr);
+   return NULL;
+}
+
+/**
+ * Closes the connection and frees the given server.
+ * @param   svr The given server.
+ * @return  Data associated with the server when it was created.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI void *
+ecore_con_server_del(Ecore_Con_Server *svr)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_del");
+       return NULL;
+     }
+   if (svr->delete_me) return NULL;
+
+   data = svr->data;
+   svr->data = NULL;
+   svr->delete_me = 1;
+   if (svr->event_count > 0)
+     {
+       if (svr->fd_handler)
+         {
+            ecore_main_fd_handler_del(svr->fd_handler);
+            svr->fd_handler = NULL;
+         }
+     }
+   else
+     {
+       _ecore_con_server_free(svr);
+     }
+   return data;
+}
+
+/**
+ * Retrieves the data associated with the given server.
+ * @param   svr The given server.
+ * @return  The associated data.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI void *
+ecore_con_server_data_get(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_data_get");
+       return NULL;
+     }
+   return svr->data;
+}
+
+/**
+ * Retrieves whether the given server is currently connected.
+ * @todo Check that this function does what the documenter believes it does.
+ * @param   svr The given server.
+ * @return  @c 1 if the server is connected.  @c 0 otherwise.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI int
+ecore_con_server_connected_get(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_connected_get");
+       return 0;
+     }
+   if (svr->connecting) return 0;
+   return 1;
+}
+
+/**
+ * Retrieves the current list of clients.
+ * @param   svr The given server.
+ * @return  The list of clients on this server.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI Eina_List *
+ecore_con_server_clients_get(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_clients_get");
+       return NULL;
+     }
+   return svr->clients;
+}
+
+/**
+ * Sends the given data to the given server.
+ * @param   svr  The given server.
+ * @param   data The given data.
+ * @param   size Length of the data, in bytes, to send.
+ * @return  The number of bytes sent.  @c 0 will be returned if there is an
+ *          error.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI int
+ecore_con_server_send(Ecore_Con_Server *svr, const void *data, int size)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_send");
+       return 0;
+     }
+   if (svr->dead) return 0;
+   if (!data) return 0;
+   if (size < 1) return 0;
+   if (svr->fd_handler)
+     ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
+   if (svr->write_buf)
+     {
+       unsigned char *newbuf;
+
+       newbuf = realloc(svr->write_buf, svr->write_buf_size + size);
+       if (newbuf) svr->write_buf = newbuf;
+       else return 0;
+       memcpy(svr->write_buf + svr->write_buf_size, data, size);
+       svr->write_buf_size += size;
+     }
+   else
+     {
+       svr->write_buf = malloc(size);
+       if (!svr->write_buf) return 0;
+       svr->write_buf_size = size;
+       memcpy(svr->write_buf, data, size);
+     }
+   return size;
+}
+
+/**
+ * Sets a limit on the number of clients that can be handled concurrently
+ * by the given server, and a policy on what to do if excess clients try to
+ * connect.
+ * Beware that if you set this once ecore is already running, you may
+ * already have pending CLIENT_ADD events in your event queue.  Those
+ * clients have already connected and will not be affected by this call.
+ * Only clients subsequently trying to connect will be affected.
+ * @param   svr           The given server.
+ * @param   client_limit  The maximum number of clients to handle
+ *                        concurrently.  -1 means unlimited (default).  0
+ *                        effectively disables the server.
+ * @param   reject_excess_clients  Set to 1 to automatically disconnect
+ *                        excess clients as soon as they connect if you are
+ *                        already handling client_limit clients.  Set to 0
+ *                        (default) to just hold off on the "accept()"
+ *                        system call until the number of active clients
+ *                        drops. This causes the kernel to queue up to 4096
+ *                        connections (or your kernel's limit, whichever is
+ *                        lower).
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI void
+ecore_con_server_client_limit_set(Ecore_Con_Server *svr, int client_limit, char reject_excess_clients)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_client_limit_set");
+       return;
+     }
+   svr->client_limit = client_limit;
+   svr->reject_excess_clients = reject_excess_clients;
+}
+
+/**
+ * Gets the IP address of a server that has been connected to.
+ *
+ * @param   svr           The given server.
+ * @return  A pointer to an internal string that contains the IP address of
+ *          the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
+ *          This string should not be modified or trusted to stay valid after
+ *          deletion for the @p svr object. If no IP is known NULL is returned.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI char *
+ecore_con_server_ip_get(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_ip_get");
+       return NULL;
+     }
+   return svr->ip;
+}
+
+/**
+ * Flushes all pending data to the given server. Will return when done.
+ *
+ * @param   svr           The given server.
+ * @ingroup Ecore_Con_Server_Group
+ */
+EAPI void
+ecore_con_server_flush(Ecore_Con_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_flush");
+       return;
+     }
+   _ecore_con_server_flush(svr);
+}
+
+/**
+ * @defgroup Ecore_Con_Client_Group Ecore Connection Client Functions
+ *
+ * Functions that operate on Ecore connection client objects.
+ */
+
+/**
+ * Sends the given data to the given client.
+ * @param   cl   The given client.
+ * @param   data The given data.
+ * @param   size Length of the data, in bytes, to send.
+ * @return  The number of bytes sent.  @c 0 will be returned if there is an
+ *          error.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI int
+ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_send");
+       return 0;
+     }
+   if (cl->dead) return 0;
+   if (!data) return 0;
+   if (size < 1) return 0;
+   if (cl->fd_handler)
+     ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
+
+   if(cl->server && cl->server->type == ECORE_CON_REMOTE_UDP)
+     {
+       sendto(cl->server->fd, data, size, 0, (struct sockaddr *) cl->client_addr, cl->client_addr_len);
+     }
+   else if (cl->buf)
+     {
+       unsigned char *newbuf;
+
+       newbuf = realloc(cl->buf, cl->buf_size + size);
+       if (newbuf) cl->buf = newbuf;
+       else return 0;
+       memcpy(cl->buf + cl->buf_size, data, size);
+       cl->buf_size += size;
+     }
+   else
+     {
+       cl->buf = malloc(size);
+       if (!cl->buf) return 0;
+       cl->buf_size = size;
+       memcpy(cl->buf, data, size);
+     }
+   return size;
+}
+
+/**
+ * Retrieves the server representing the socket the client has
+ * connected to.
+ * @param   cl The given client.
+ * @return  The server that the client connected to.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI Ecore_Con_Server *
+ecore_con_client_server_get(Ecore_Con_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_server_get");
+       return NULL;
+     }
+   return cl->server;
+}
+
+/**
+ * Closes the connection and frees memory allocated to the given client.
+ * @param   cl The given client.
+ * @return  Data associated with the client.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI void *
+ecore_con_client_del(Ecore_Con_Client *cl)
+{
+   void *data = NULL;
+
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_del");
+       return NULL;
+     }
+
+   if(cl->client_addr && cl->server && (cl->server->type == ECORE_CON_REMOTE_UDP ||
+                                cl->server->type == ECORE_CON_REMOTE_MCAST))
+     free(cl->client_addr);
+
+   data = cl->data;
+
+   cl->data = NULL;
+   cl->delete_me = 1;
+   if (cl->event_count > 0)
+     {
+       if (cl->fd_handler)
+         {
+            ecore_main_fd_handler_del(cl->fd_handler);
+            cl->fd_handler = NULL;
+         }
+     }
+   else
+     {
+        if (cl->server)
+         cl->server->clients = eina_list_remove(cl->server->clients, cl);
+       _ecore_con_client_free(cl);
+     }
+   return data;
+}
+
+/**
+ * Sets the data associated with the given client to @p data.
+ * @param   cl   The given client.
+ * @param   data What to set the data to.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI void
+ecore_con_client_data_set(Ecore_Con_Client *cl, const void *data)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_data_set");
+       return;
+     }
+   cl->data = (void *)data;
+}
+
+/**
+ * Retrieves the data associated with the given client.
+ * @param   cl The given client.
+ * @return  The data associated with @p cl.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI void *
+ecore_con_client_data_get(Ecore_Con_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_data_get");
+       return NULL;
+     }
+   return cl->data;
+}
+
+/**
+ * Gets the IP address of a cleint that has connected.
+ *
+ * @param   cl            The given client.
+ * @return  A pointer to an internal string that contains the IP address of
+ *          the connected client in the form "XXX.YYY.ZZZ.AAA" IP notation.
+ *          This string should not be modified or trusted to stay valid after
+ *          deletion for the @p cl object. If no IP is known NULL is returned.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI char *
+ecore_con_client_ip_get(Ecore_Con_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_ip_get");
+       return NULL;
+     }
+   return cl->ip;
+}
+
+/**
+ * Flushes all pending data to the given client. Will return when done.
+ *
+ * @param   cl            The given client.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI void
+ecore_con_client_flush(Ecore_Con_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_flush");
+       return;
+     }
+   _ecore_con_client_flush(cl);
+}
+
+static void
+_ecore_con_server_free(Ecore_Con_Server *svr)
+{
+   Ecore_Con_Client *cl;
+   double t_start, t;
+
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE);
+   t_start = ecore_time_get();
+   while ((svr->write_buf) && (!svr->dead))
+     {
+       _ecore_con_server_flush(svr);
+       t = ecore_time_get();
+       if ((t - t_start) > 0.5)
+         {
+           WRN("ECORE_CON: EEK - stuck in _ecore_con_server_free() trying\n"
+                "  to flush data out from the server, and have been for\n"
+                "  %1.1f seconds. This is taking too long. Aborting flush.",
+                (t - t_start));
+            break;
+         }
+     }
+   if (svr->write_buf) free(svr->write_buf);
+   EINA_LIST_FREE(svr->clients, cl)
+       _ecore_con_client_free(cl);
+   if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
+     unlink(svr->path);
+   if (svr->fd >= 0) close(svr->fd);
+   ecore_con_ssl_server_shutdown(svr);
+   if (svr->name) free(svr->name);
+   if (svr->path) free(svr->path);
+   if (svr->ip) free(svr->ip);
+   if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
+   servers = eina_list_remove(servers, svr);
+   free(svr);
+}
+
+static void
+_ecore_con_client_free(Ecore_Con_Client *cl)
+{
+   double t_start, t;
+
+   ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE);
+   t_start = ecore_time_get();
+   while ((cl->buf) && (!cl->dead))
+     {
+       _ecore_con_client_flush(cl);
+       t = ecore_time_get();
+       if ((t - t_start) > 0.5)
+         {
+            WRN("EEK - stuck in _ecore_con_client_free() trying\n"
+                "  to flush data out from the client, and have been for\n"
+                "  %1.1f seconds. This is taking too long. Aborting flush.",
+                (t - t_start));
+            break;
+         }
+     }
+   if (cl->buf) free(cl->buf);
+   if (cl->fd >= 0) close(cl->fd);
+   if (cl->fd_handler) ecore_main_fd_handler_del(cl->fd_handler);
+   if (cl->ip) free(cl->ip);
+   free(cl);
+}
+
+static void
+kill_server(Ecore_Con_Server *svr)
+{
+   if (!svr->delete_me)
+     {
+       Ecore_Con_Event_Server_Del *e;
+
+       e = calloc(1, sizeof(Ecore_Con_Event_Server_Del));
+       if (e)
+         {
+            svr->event_count++;
+            e->server = svr;
+            ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, e,
+                            _ecore_con_event_server_del_free, NULL);
+         }
+     }
+
+   svr->dead = 1;
+   if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
+   svr->fd_handler = NULL;
+}
+
+static void
+_ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *net_info)
+{
+   Ecore_Con_Server *svr;
+   struct linger lin;
+
+   svr = data;
+
+   if(!net_info) goto error;
+
+   svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+   if (svr->fd < 0) goto error;
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+   lin.l_onoff = 1;
+   lin.l_linger = 0;
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin, sizeof(struct linger)) < 0) goto error;
+   if (svr->type == ECORE_CON_REMOTE_NODELAY)
+     {
+       int flag = 1;
+
+       if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) < 0)
+         goto error;
+     }
+   if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error;
+   if (listen(svr->fd, 4096) < 0) goto error;
+   svr->fd_handler =
+     ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                              _ecore_con_svr_handler, svr, NULL, NULL);
+   if (!svr->fd_handler) goto error;
+
+   return;
+
+   error:
+   ecore_con_ssl_server_shutdown(svr);
+   kill_server(svr);
+}
+
+static void
+_ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *net_info)
+{
+   Ecore_Con_Server *svr;
+   Ecore_Con_Type type;
+   struct ip_mreq mreq;
+   struct ipv6_mreq mreq6;
+   const int on = 1;
+
+   svr = data;
+   type = svr->type;
+   type &= ECORE_CON_TYPE;
+
+   if (!net_info) goto error;
+
+   svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+   if(svr->fd < 0) goto error;
+
+   if (type == ECORE_CON_REMOTE_MCAST)
+     {
+       if (net_info->info.ai_family == AF_INET)
+        {
+          if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq.imr_multiaddr)) goto error;
+          mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+          if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq,sizeof(mreq)) != 0) goto error;
+        }
+       else if (net_info->info.ai_family == AF_INET6)
+        {
+          if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq6.ipv6mr_multiaddr)) goto error;
+          mreq6.ipv6mr_interface = htonl(INADDR_ANY);
+          if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq6,sizeof(mreq6)) != 0) goto error;
+        }
+       if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0) goto error;
+     }
+
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+   if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error;
+   svr->fd_handler =
+     ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                              _ecore_con_svr_udp_handler, svr, NULL, NULL);
+   if (!svr->fd_handler) goto error;
+   svr->ip = strdup(net_info->ip);
+
+   return;
+
+   error:
+   ecore_con_ssl_server_shutdown(svr);
+   kill_server(svr);
+}
+
+static void
+_ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *net_info)
+{
+   Ecore_Con_Server   *svr;
+   int                 res;
+   int                 curstate = 0;
+
+   svr = data;
+
+   if (!net_info) goto error;
+   svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+   if (svr->fd < 0) goto error;
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0)
+     goto error;
+   if (svr->type == ECORE_CON_REMOTE_NODELAY)
+     {
+       int flag = 1;
+
+       if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) < 0)
+         goto error;
+     }
+   res = connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen);
+#ifdef _WIN32
+   if (res == SOCKET_ERROR)
+     {
+       if (WSAGetLastError() != WSAEINPROGRESS)
+        goto error;
+#else
+   if (res < 0)
+     {
+       if (errno != EINPROGRESS)
+        goto error;
+#endif
+       svr->connecting = 1;
+       svr->fd_handler =
+        ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
+                                  _ecore_con_cl_handler, svr, NULL, NULL);
+     }
+   else
+     svr->fd_handler =
+       ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                                _ecore_con_cl_handler, svr, NULL, NULL);
+
+   if (svr->type & ECORE_CON_SSL)
+     if (ecore_con_ssl_server_init(svr))
+       goto error;
+
+   if (!svr->fd_handler) goto error;
+   svr->ip = strdup(net_info->ip);
+
+   return;
+
+   error:
+   ecore_con_ssl_server_shutdown(svr);
+   kill_server(svr);
+}
+
+static void
+_ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *net_info)
+{
+   Ecore_Con_Server   *svr;
+   int                 curstate = 0;
+   int                broadcast = 1;
+   svr = data;
+
+   if (!net_info) goto error;
+   svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+   if (svr->fd < 0) goto error;
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+
+   if(svr->type == ECORE_CON_REMOTE_BROADCAST)
+     {
+       if (setsockopt(svr->fd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast)) < 0) goto error;
+     }
+   else
+     {
+       if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0) goto error;
+     }
+
+   if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
+     goto error;
+   else
+     svr->fd_handler =
+       ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
+                                _ecore_con_cl_udp_handler, svr, NULL, NULL);
+   if (!svr->fd_handler) goto error;
+   svr->ip = strdup(net_info->ip);
+
+   return;
+
+   error:
+   ecore_con_ssl_server_shutdown(svr);
+   kill_server(svr);
+}
+
+static Ecore_Con_State
+svr_try_connect_plain(Ecore_Con_Server *svr)
+{
+   int          res;
+   int          so_err = 0;
+   unsigned int size = sizeof(int);
+
+   res = getsockopt(svr->fd, SOL_SOCKET, SO_ERROR, (void *)&so_err, &size);
+#ifdef _WIN32
+   if (res == SOCKET_ERROR)
+     so_err = -1;
+
+   if (so_err == WSAEINPROGRESS && !svr->dead)
+     return ECORE_CON_INPROGRESS;
+#else
+   if (res < 0)
+     so_err = -1;
+
+   if (so_err == EINPROGRESS && !svr->dead)
+     return ECORE_CON_INPROGRESS;
+#endif
+
+   if (so_err != 0)
+     {
+       /* we lost our server! */
+       kill_server(svr);
+       return ECORE_CON_DISCONNECTED;
+     }
+   else
+     {
+       if (!svr->delete_me)
+         {
+            /* we got our server! */
+            Ecore_Con_Event_Server_Add *e;
+
+            svr->connecting = 0;
+            e = calloc(1, sizeof(Ecore_Con_Event_Server_Add));
+            if (e)
+              {
+                 svr->event_count++;
+                 e->server = svr;
+                 ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e,
+                                 _ecore_con_event_server_add_free, NULL);
+              }
+         }
+       if (svr->fd_handler)
+         {
+            if (!svr->write_buf)
+              ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+         }
+     }
+
+   if (!svr->dead)
+     return ECORE_CON_CONNECTED;
+   else
+     return ECORE_CON_DISCONNECTED;
+}
+
+/* returns 1 on success, 0 on failure */
+static Ecore_Con_State svr_try_connect(Ecore_Con_Server *svr)
+{
+  if (!(svr->type & ECORE_CON_SSL))
+    return svr_try_connect_plain(svr);
+  else
+    {
+      switch (ecore_con_ssl_server_try(svr)) {
+      case ECORE_CON_CONNECTED:
+       return svr_try_connect_plain(svr);
+      case ECORE_CON_DISCONNECTED:
+       kill_server(svr);
+       return ECORE_CON_DISCONNECTED;
+      default:
+       return ECORE_CON_INPROGRESS;
+      }
+    }
+}
+
+static char *
+_ecore_con_pretty_ip(struct sockaddr *client_addr, socklen_t size)
+{
+   char ipbuf[INET6_ADDRSTRLEN + 1];
+
+   /* show v4mapped address in pretty form */
+   if (client_addr->sa_family == AF_INET6)
+     {
+       struct sockaddr_in6 *sa6;
+
+       sa6 = (struct sockaddr_in6 *) client_addr;
+       if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
+         {
+            snprintf(ipbuf, sizeof (ipbuf), "%u.%u.%u.%u",
+                     sa6->sin6_addr.s6_addr[12],
+                     sa6->sin6_addr.s6_addr[13],
+                     sa6->sin6_addr.s6_addr[14],
+                     sa6->sin6_addr.s6_addr[15]);
+            return strdup(ipbuf);
+         }
+     }
+
+   if (getnameinfo(client_addr, size,
+                  ipbuf, sizeof (ipbuf), NULL, 0, NI_NUMERICHOST))
+     return strdup("0.0.0.0");
+
+   ipbuf[sizeof (ipbuf) - 1] = 0;
+   return strdup(ipbuf);
+}
+
+static int
+_ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Ecore_Con_Server   *svr;
+   int                 new_fd;
+   unsigned char       incoming[256];
+   size_t              size_in;
+
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
+   if ((svr->client_limit >= 0) && (!svr->reject_excess_clients))
+     {
+       if (eina_list_count(svr->clients) >= (unsigned int)svr->client_limit)
+         return 1;
+     }
+   /* a new client */
+   size_in = sizeof(incoming);
+
+   memset(&incoming, 0, size_in);
+   new_fd = accept(svr->fd, (struct sockaddr *)&incoming, (socklen_t *)&size_in);
+   if (new_fd >= 0)
+     {
+       Ecore_Con_Client *cl;
+
+       if ((svr->client_limit >= 0) && (svr->reject_excess_clients))
+         {
+           if (eina_list_count(svr->clients) >= (unsigned int)svr->client_limit)
+             {
+               close(new_fd);
+               return 1;
+             }
+         }
+
+       cl = calloc(1, sizeof(Ecore_Con_Client));
+       if (!cl)
+         {
+            close(new_fd);
+            return 1;
+         }
+
+       fcntl(new_fd, F_SETFL, O_NONBLOCK);
+       fcntl(new_fd, F_SETFD, FD_CLOEXEC);
+       cl->fd = new_fd;
+       cl->server = svr;
+
+       if ((svr->type & ECORE_CON_SSL) &&
+           (ecore_con_ssl_client_init(cl)))
+         {
+           close(new_fd);
+           ecore_con_ssl_client_shutdown(cl);
+           return 1;
+         }
+
+       cl->fd_handler =
+         ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
+                                   _ecore_con_svr_cl_handler, cl, NULL, NULL);
+       ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+       svr->clients = eina_list_append(svr->clients, cl);
+       if (!svr->path)
+         cl->ip = _ecore_con_pretty_ip((struct sockaddr *) &incoming, size_in);
+       if (!cl->delete_me)
+         {
+            Ecore_Con_Event_Client_Add *e;
+
+            e = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
+            if (e)
+              {
+                 cl->event_count++;
+                 e->client = cl;
+                 ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, e,
+                                 _ecore_con_event_client_add_free, NULL);
+              }
+         }
+     }
+   return 1;
+}
+
+static int
+_ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   Ecore_Con_Server   *svr;
+
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
+   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+     {
+       unsigned char *inbuf = NULL;
+       int            inbuf_num = 0;
+
+       if (svr->connecting && (svr_try_connect(svr) != ECORE_CON_CONNECTED))
+          return 1;
+
+       for (;;)
+         {
+           int num;
+           int lost_server = 1;
+           unsigned char buf[READBUFSIZ];
+
+           if (!(svr->type & ECORE_CON_SSL))
+             {
+               if (((num = read(svr->fd, buf, READBUFSIZ)) < 0) &&
+                   (errno == EAGAIN))
+                 lost_server = 0;
+             }
+           else
+             if (!(num = ecore_con_ssl_server_read(svr, buf, READBUFSIZ)))
+                 lost_server = 0;
+
+           if (num < 1)
+             {
+               if (inbuf && !svr->delete_me)
+                 {
+                   Ecore_Con_Event_Server_Data *e;
+
+                   e = calloc(1, sizeof(Ecore_Con_Event_Server_Data));
+                   if (e)
+                     {
+                       svr->event_count++;
+                       e->server = svr;
+                       e->data = inbuf;
+                       e->size = inbuf_num;
+                       ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
+                                       _ecore_con_event_server_data_free,
+                                       NULL);
+                     }
+                 }
+               if (lost_server) kill_server(svr);
+               break;
+             }
+
+           inbuf = realloc(inbuf, inbuf_num + num);
+           memcpy(inbuf + inbuf_num, buf, num);
+           inbuf_num += num;
+         }
+
+/* #if USE_OPENSSL */
+/*     if (svr->fd_handler) */
+/*       { */
+/*          if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ) */
+/*            ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); */
+/*          else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE) */
+/*            ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); */
+/*       } */
+/* #endif */
+     }
+   else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
+     {
+       if (svr->connecting && !svr_try_connect (svr))
+          return 1;
+       _ecore_con_server_flush(svr);
+     }
+
+   return 1;
+}
+
+static int
+_ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   Ecore_Con_Server   *svr;
+
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
+   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+     {
+       unsigned char buf[65536];
+       int           num = 0;
+
+       errno = 0;
+       num = read(svr->fd, buf, 65536);
+       if (num > 0)
+        {
+          if (!svr->delete_me)
+            {
+              Ecore_Con_Event_Server_Data *e;
+              unsigned char *inbuf;
+
+              inbuf = malloc(num);
+              if(inbuf == NULL)
+                return 1;
+              memcpy(inbuf, buf, num);
+
+              e = calloc(1, sizeof(Ecore_Con_Event_Server_Data));
+              if (e)
+                {
+                  svr->event_count++;
+                  e->server = svr;
+                  e->data = inbuf;
+                  e->size = num;
+                  ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
+                                  _ecore_con_event_server_data_free,
+                                  NULL);
+                }
+            }
+        }
+     }
+   else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
+       _ecore_con_server_flush(svr);
+
+   return 1;
+}
+
+static int
+_ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   Ecore_Con_Server   *svr;
+   Ecore_Con_Client *cl = NULL;
+
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
+   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+     {
+       unsigned char buf[READBUFSIZ];
+       unsigned char client_addr[256];
+       unsigned int client_addr_len = sizeof(client_addr);
+       int num;
+
+       errno = 0;
+#ifdef _WIN32
+       num = fcntl(svr->fd, F_SETFL, O_NONBLOCK);
+       if (num >= 0)
+         num = recvfrom(svr->fd, buf, sizeof(buf), 0, (struct sockaddr*) &client_addr, &client_addr_len);
+#else
+       num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*) &client_addr, &client_addr_len);
+#endif
+
+       if (num > 0)
+        {
+          if (!svr->delete_me)
+            {
+              Ecore_Con_Event_Client_Data *e;
+              unsigned char *inbuf;
+
+              /* Create a new client for use in the client data event */
+              cl = calloc(1, sizeof(Ecore_Con_Client));
+              if(cl == NULL)
+                return 1;
+              cl->buf = NULL;
+              cl->fd = 0;
+              cl->fd_handler = NULL;
+              cl->server = svr;
+              cl->client_addr = calloc(1, client_addr_len);
+              cl->client_addr_len = client_addr_len;
+              if(cl->client_addr == NULL)
+                {
+                  free(cl);
+                  return 1;
+                }
+              memcpy(cl->client_addr, &client_addr, client_addr_len);
+              ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+              svr->clients = eina_list_append(svr->clients, cl);
+
+              cl->ip = _ecore_con_pretty_ip(cl->client_addr, cl->client_addr_len);
+
+              inbuf = malloc(num);
+              if(inbuf == NULL)
+                {
+                  free(cl->client_addr);
+                  free(cl);
+                  return 1;
+                }
+
+              memcpy(inbuf, buf, num);
+
+              e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
+              if (e)
+                {
+                  svr->event_count++;
+                  e->client = cl;
+                  e->data = inbuf;
+                  e->size = num;
+                  ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
+                                  _ecore_con_event_client_data_free,
+                                  NULL);
+                }
+
+              if(!cl->delete_me)
+                {
+                  Ecore_Con_Event_Client_Add *add;
+
+                  add = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
+                  if(add)
+                    {
+                      /*cl->event_count++;*/
+                      add->client = cl;
+                      ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, add,
+                                      _ecore_con_event_client_add_free, NULL);
+                    }
+                }
+            }
+          if ((errno == EIO) ||  (errno == EBADF) ||
+              (errno == EPIPE) || (errno == EINVAL) ||
+              (errno == ENOSPC) || (num == 0)/* is num == 0 right? */)
+            {
+              if (!svr->delete_me)
+                {
+                  /* we lost our client! */
+                  Ecore_Con_Event_Client_Del *e;
+
+                  e = calloc(1, sizeof(Ecore_Con_Event_Client_Del));
+                  if (e)
+                    {
+                      svr->event_count++;
+                      e->client = cl;
+                      ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
+                                      _ecore_con_event_client_del_free,
+                                      NULL);
+                    }
+                }
+              svr->dead = 1;
+              if (svr->fd_handler)
+                ecore_main_fd_handler_del(svr->fd_handler);
+              svr->fd_handler = NULL;
+            }
+        }
+     }
+   else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
+     _ecore_con_client_flush(cl);
+   return 1;
+}
+
+static int
+_ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   Ecore_Con_Client   *cl;
+
+   cl = data;
+   if (cl->dead) return 1;
+   if (cl->delete_me) return 1;
+   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+     {
+       unsigned char *inbuf = NULL;
+       int            inbuf_num = 0;
+       int            lost_client = 1;
+
+       for (;;)
+         {
+            unsigned char buf[65536];
+            int num;
+
+            errno = 0;
+
+            if (!(cl->server->type & ECORE_CON_SSL))
+              {
+                if (((num = read(cl->fd, buf, 65536)) < 0) &&
+                    (errno == EAGAIN))
+                  lost_client = 0;
+              }
+            else
+              if (!(num = ecore_con_ssl_client_read(cl, buf, 65536)))
+                lost_client = 0;
+
+            if (num < 1)
+              {
+                 if (inbuf && !cl->delete_me)
+                   {
+                     Ecore_Con_Event_Client_Data *e;
+
+                     e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
+                     if (e)
+                       {
+                         cl->event_count++;
+                         e->client = cl;
+                         e->data = inbuf;
+                         e->size = inbuf_num;
+                         ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
+                                         _ecore_con_event_client_data_free,
+                                         NULL);
+                       }
+                   }
+
+                 if (lost_client)
+                   {
+                      if (!cl->delete_me)
+                        {
+                           /* we lost our client! */
+                           Ecore_Con_Event_Client_Del *e;
+
+                           e = calloc(1, sizeof(Ecore_Con_Event_Client_Del));
+                           if (e)
+                             {
+                                cl->event_count++;
+                                e->client = cl;
+                                ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
+                                                _ecore_con_event_client_del_free,
+                                                NULL);
+                             }
+                        }
+                      cl->dead = 1;
+                      if (cl->fd_handler)
+                        ecore_main_fd_handler_del(cl->fd_handler);
+                      cl->fd_handler = NULL;
+                   }
+                 break;
+              }
+            else
+              {
+                 inbuf = realloc(inbuf, inbuf_num + num);
+                 memcpy(inbuf + inbuf_num, buf, num);
+                 inbuf_num += num;
+              }
+         }
+     }
+   else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
+     _ecore_con_client_flush(cl);
+   return 1;
+}
+
+static void
+_ecore_con_server_flush(Ecore_Con_Server *svr)
+{
+   int count, num;
+
+   if (!svr->write_buf) return;
+
+   /* check whether we need to write anything at all.
+    * we must not write zero bytes with SSL_write() since it
+    * causes undefined behaviour
+    */
+   if (svr->write_buf_size == svr->write_buf_offset)
+      return;
+
+   num = svr->write_buf_size - svr->write_buf_offset;
+
+   if (!(svr->type & ECORE_CON_SSL))
+     count = write(svr->fd, svr->write_buf + svr->write_buf_offset, num);
+   else
+     count = ecore_con_ssl_server_write(svr, svr->write_buf + svr->write_buf_offset, num);
+
+   if (count < 0)
+     {
+       /* we lost our server! */
+       kill_server(svr);
+       return;
+     }
+
+   svr->write_buf_offset += count;
+   if (svr->write_buf_offset >= svr->write_buf_size)
+     {
+       svr->write_buf_size = 0;
+       svr->write_buf_offset = 0;
+       free(svr->write_buf);
+       svr->write_buf = NULL;
+       if (svr->fd_handler)
+         ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+     }
+}
+
+static void
+_ecore_con_client_flush(Ecore_Con_Client *cl)
+{
+   int count, num;
+
+   if (!cl->buf) return;
+   num = cl->buf_size - cl->buf_offset;
+   if (!(cl->server->type & ECORE_CON_SSL))
+     count = write(cl->fd, cl->buf + cl->buf_offset, num);
+   else
+     count = ecore_con_ssl_client_write(cl, cl->buf + cl->buf_offset, num);
+   if (count < 1)
+     {
+       if ((errno == EIO) || (errno == EBADF) || (errno == EPIPE) ||
+           (errno == EINVAL) || (errno == ENOSPC))
+         {
+            if (!cl->delete_me)
+              {
+                 /* we lost our client! */
+                 Ecore_Con_Event_Client_Del *e;
+
+                 e = calloc(1, sizeof(Ecore_Con_Event_Client_Del));
+                 if (e)
+                   {
+                      cl->event_count++;
+                      e->client = cl;
+                      ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
+                                      _ecore_con_event_client_del_free, NULL);
+                   }
+                 cl->dead = 1;
+                 if (cl->fd_handler)
+                   ecore_main_fd_handler_del(cl->fd_handler);
+                 cl->fd_handler = NULL;
+              }
+         }
+       return;
+     }
+   cl->buf_offset += count;
+   if (cl->buf_offset >= cl->buf_size)
+     {
+       cl->buf_size = 0;
+       cl->buf_offset = 0;
+       free(cl->buf);
+       cl->buf = NULL;
+       if (cl->fd_handler)
+         ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
+     }
+}
+
+static void
+_ecore_con_event_client_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Add *e;
+
+   e = ev;
+   e->client->event_count--;
+   if ((e->client->event_count == 0) && (e->client->delete_me))
+     ecore_con_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_con_event_client_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Del *e;
+
+   e = ev;
+   e->client->event_count--;
+   if ((e->client->event_count == 0) && (e->client->delete_me))
+     ecore_con_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_con_event_client_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Data *e;
+
+   e = ev;
+   e->client->event_count--;
+   if (e->data) free(e->data);
+   if (((e->client->event_count == 0) && (e->client->delete_me)) ||
+       ((e->client->server && (e->client->server->type == ECORE_CON_REMOTE_UDP ||
+                              e->client->server->type == ECORE_CON_REMOTE_MCAST))))
+     ecore_con_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_con_event_server_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Add *e;
+
+   e = ev;
+   e->server->event_count--;
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     _ecore_con_server_free(e->server);
+   free(e);
+}
+
+static void
+_ecore_con_event_server_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Del *e;
+
+   e = ev;
+   e->server->event_count--;
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     _ecore_con_server_free(e->server);
+   free(e);
+}
+
+static void
+_ecore_con_event_server_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Data *e;
+
+   e = ev;
+   e->server->event_count--;
+   if (e->data) free(e->data);
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     _ecore_con_server_free(e->server);
+   free(e);
+}
diff --git a/src/lib/ecore_con/ecore_con_ares.c b/src/lib/ecore_con/ecore_con_ares.c
new file mode 100644 (file)
index 0000000..a6f2430
--- /dev/null
@@ -0,0 +1,484 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * This version of ecore_con_info use c-ares to provide asynchronous dns lookup.
+ *
+ * Note: It doesn't fork nor does it use libc getaddrinfo.
+ * http://c-ares.haxx.se/docs.html
+ */
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <ares.h>
+
+#include "Ecore.h"
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+typedef struct _Ecore_Con_FD Ecore_Con_FD;
+typedef struct _Ecore_Con_CAres Ecore_Con_CAres;
+
+struct _Ecore_Con_FD
+{
+   Ecore_Fd_Handler *handler;
+   int active;
+   int fd;
+};
+
+struct _Ecore_Con_CAres
+{
+   Ecore_Con_Server *svr;
+   Ecore_Con_Info_Cb done_cb;
+   void *data;
+   struct addrinfo hints;
+   Ecore_Con_Info *result;
+
+   union {
+      struct in_addr v4;
+      struct in6_addr v6;
+   } addr;
+
+   Eina_Bool byaddr;
+};
+
+static ares_channel info_channel;
+static int info_init = 0;
+static Eina_List *info_fds = NULL;
+static int active = 0;
+static Ecore_Timer *tm = NULL;
+static fd_set info_readers, info_writers;
+
+static void _ecore_con_info_ares_nameinfo(Ecore_Con_CAres *arg, int status, int timeouts, char *node, char *service);
+static void _ecore_con_info_ares_host_cb(Ecore_Con_CAres *arg, int status, int timeouts, struct hostent *hostent);
+static int _ecore_con_info_cares_fd_cb(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_info_cares_timeout_cb(void *data);
+static void _ecore_con_info_cares_clean(void);
+
+int
+ecore_con_info_init(void)
+{
+   if (info_init == 0)
+     {
+       if (ares_library_init(ARES_LIB_INIT_ALL) != 0)
+         return 0;
+       if (ares_init(&info_channel) != ARES_SUCCESS)
+         {
+            ares_library_cleanup();
+            return 0;
+         }
+     }
+
+   info_init++;
+   return info_init;
+}
+
+int
+ecore_con_info_shutdown(void)
+{
+   info_init--;
+   if (info_init == 0)
+     {
+       /* Cancel all ongoing request */
+       ares_cancel(info_channel);
+       ares_destroy(info_channel);
+
+       /* Destroy FD handler here. */
+       /* Shutdown ares */
+       ares_library_cleanup();
+     }
+   return info_init;
+}
+
+int
+ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_STREAM;
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_protocol = IPPROTO_TCP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_STREAM;
+   hints.ai_flags = AI_PASSIVE;
+   hints.ai_protocol = IPPROTO_TCP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_connect(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = AI_PASSIVE;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = 0;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+EAPI int
+ecore_con_info_get(Ecore_Con_Server *svr,
+                  Ecore_Con_Info_Cb done_cb,
+                  void *data,
+                  struct addrinfo *hints)
+{
+   Ecore_Con_CAres *cares;
+   int ai_family = AF_UNSPEC;
+
+   cares = calloc(1, sizeof (Ecore_Con_CAres));
+   if (!cares) return 0;
+
+   cares->svr = svr;
+   cares->done_cb = done_cb;
+   cares->data = data;
+
+   if (hints)
+     {
+       ai_family = hints->ai_family;
+       memcpy(&cares->hints, hints, sizeof (struct addrinfo));
+     }
+
+   if (inet_pton(AF_INET, svr->name, &cares->addr.v4) == 1)
+     {
+       cares->byaddr = EINA_TRUE;
+       ares_gethostbyaddr(info_channel, &cares->addr.v4, sizeof (cares->addr.v4), AF_INET, (ares_host_callback) _ecore_con_info_ares_host_cb, cares);
+     }
+   else if (inet_pton(AF_INET6, svr->name, &cares->addr.v6) == 1)
+     {
+       cares->byaddr = EINA_TRUE;
+       ares_gethostbyaddr(info_channel, &cares->addr.v6, sizeof (cares->addr.v6), AF_INET6, (ares_host_callback) _ecore_con_info_ares_host_cb, cares);
+     }
+   else
+     {
+       cares->byaddr = EINA_FALSE;
+       ares_gethostbyname(info_channel, svr->name, ai_family, (ares_host_callback) _ecore_con_info_ares_host_cb, cares);
+     }
+
+   _ecore_con_info_cares_clean();
+
+   return 1;
+}
+
+static int
+_ecore_con_info_fds_search(const Ecore_Con_FD *fd1, const Ecore_Con_FD *fd2)
+{
+   return fd1->fd - fd2->fd;
+}
+
+static Eina_Bool
+_ecore_con_info_fds_lookup(int fd)
+{
+   Ecore_Con_FD fdl;
+   Ecore_Con_FD *search;
+
+   fdl.fd = fd;
+
+   search = eina_list_search_unsorted(info_fds, (Eina_Compare_Cb) _ecore_con_info_fds_search, &fdl);
+
+   if (search)
+     {
+       search->active = active;
+       return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+static void
+_ecore_con_info_cares_clean(void)
+{
+   fd_set readers, writers;
+   Eina_List *l, *l_next;
+   Ecore_Con_FD *ecf;
+   int nfds;
+   int i;
+
+   FD_ZERO(&readers);
+   FD_ZERO(&writers);
+   nfds = ares_fds(info_channel, &readers, &writers);
+
+   active++;
+   for (i = 0; i < nfds; ++i)
+     {
+       int flags = 0;
+
+       if (FD_ISSET(i, &readers)) flags |= ECORE_FD_READ;
+       if (FD_ISSET(i, &writers)) flags |= ECORE_FD_WRITE;
+
+       if (flags)
+         {
+            if (!_ecore_con_info_fds_lookup(i))
+              {
+                 ecf = malloc(sizeof (Ecore_Con_FD));
+                 if (ecf)
+                   {
+                      ecf->fd = i;
+                      ecf->active = active;
+                      ecf->handler = ecore_main_fd_handler_add(i, ECORE_FD_WRITE | ECORE_FD_READ,
+                                                               _ecore_con_info_cares_fd_cb,
+                                                               NULL, NULL, NULL);
+                      info_fds = eina_list_append(info_fds, ecf);
+                   }
+              }
+         }
+     }
+
+   info_readers = readers;
+   info_writers = writers;
+
+   EINA_LIST_FOREACH_SAFE(info_fds, l, l_next, ecf)
+     {
+       if (ecf->active != active)
+         {
+            ecore_main_fd_handler_del(ecf->handler);
+            free(ecf);
+            info_fds = eina_list_remove_list(info_fds, l);
+         }
+     }
+
+   if (!info_fds)
+     {
+       if (tm) ecore_timer_del(tm);
+       tm = NULL;
+     }
+   else
+     {
+       struct timeval tv;
+
+       ares_timeout(info_channel, NULL, &tv);
+
+       if (tm)
+         ecore_timer_delay(tm, tv.tv_sec);
+       else
+         tm = ecore_timer_add((double) tv.tv_sec, _ecore_con_info_cares_timeout_cb, NULL);
+     }
+}
+
+static int
+_ecore_con_info_cares_timeout_cb(void *data)
+{
+   ares_process(info_channel, &info_readers, &info_writers);
+   _ecore_con_info_cares_clean();
+
+   return 1;
+}
+
+static int
+_ecore_con_info_cares_fd_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   ares_process(info_channel, &info_readers, &info_writers);
+   _ecore_con_info_cares_clean();
+
+   return 1;
+}
+
+static void
+_ecore_con_info_ares_host_cb(Ecore_Con_CAres *arg, int status, int timeouts, struct hostent *hostent)
+{
+   struct sockaddr *addr;
+   int addrlen;
+   int length = 0;
+
+   /* Found something ? */
+   switch (status)
+     {
+      case ARES_SUCCESS:
+        if (hostent->h_addr_list[0] == NULL)
+          {
+             fprintf(stderr, "No IP found\n");
+             goto on_error;
+          }
+
+        switch (hostent->h_addrtype)
+          {
+           case AF_INET:
+             {
+                struct sockaddr_in *addri;
+
+                addrlen = sizeof (struct sockaddr_in);
+                addri = malloc(addrlen);
+
+                if (!addri)
+                  {
+                     fprintf(stderr, "Not enough memory\n");
+                     goto on_error;
+                  }
+
+                addri->sin_family = AF_INET;
+                addri->sin_port = htons(arg->svr->port);
+
+                memcpy(&addri->sin_addr.s_addr, arg->byaddr ? &arg->addr.v4 : (struct in_addr*)hostent->h_addr_list[0], sizeof (struct in_addr));
+
+                addr = (struct sockaddr*) addri;
+                break;
+             }
+           case AF_INET6:
+             {
+                struct sockaddr_in6 *addri6;
+
+                addrlen = sizeof (struct sockaddr_in6);
+                addri6 = malloc(addrlen);
+
+                if (!addri6)
+                  {
+                     fprintf(stderr, "Not enough memory\n");
+                     goto on_error;
+                  }
+
+                addri6->sin6_family = AF_INET6;
+                addri6->sin6_port = htons(arg->svr->port);
+                addri6->sin6_flowinfo = 0;
+                addri6->sin6_scope_id = 0;
+
+                memcpy(&addri6->sin6_addr.s6_addr, arg->byaddr ? &arg->addr.v6 : (struct in6_addr*)hostent->h_addr_list[0], sizeof (struct in6_addr));
+
+                addr = (struct sockaddr*) addri6;
+                break;
+             }
+           default:
+              fprintf(stderr, "Unknown addrtype %i\n", hostent->h_addrtype);
+              goto on_error;
+          }
+
+        if (hostent->h_name)
+          length = strlen(hostent->h_name) + 1;
+
+        arg->result = malloc(sizeof (Ecore_Con_Info) + length);
+        if (!arg->result)
+          {
+             fprintf(stderr, "Not enough memory\n");
+             free(addr);
+             goto on_error;
+          }
+
+        /* FIXME: What to do when hint is not set ? */
+        arg->result->info.ai_flags = arg->hints.ai_flags;
+        arg->result->info.ai_socktype = arg->hints.ai_socktype;
+        arg->result->info.ai_protocol = arg->hints.ai_protocol;
+
+        arg->result->info.ai_family = hostent->h_addrtype;
+        arg->result->info.ai_addrlen = addrlen;
+        arg->result->info.ai_addr = addr;
+        arg->result->info.ai_canonname = (char*) (arg->result + 1);
+
+        strcpy(arg->result->info.ai_canonname, hostent->h_name);
+
+        arg->result->info.ai_next = NULL;
+
+        ares_getnameinfo(info_channel, addr, addrlen,
+                         ARES_NI_NUMERICSERV | ARES_NI_NUMERICHOST | ARES_NI_LOOKUPSERVICE | ARES_NI_LOOKUPHOST,
+                         (ares_nameinfo_callback) _ecore_con_info_ares_nameinfo, arg);
+        break;
+      case ARES_ENOTIMP: /* unknown family */
+      case ARES_EBADNAME: /* not a valid internet address */
+      case ARES_ENOTFOUND: /* address notfound */
+      case ARES_ENOMEM: /* not enough memory */
+      case ARES_EDESTRUCTION: /* request canceled, shuting down */
+        goto on_error;
+      default:
+        fprintf(stderr, "Unknown status returned by c-ares: %i assuming error\n", status);
+        goto on_error;
+     }
+
+   return ;
+
+ on_error:
+   arg->done_cb(arg->data, NULL);
+   free(arg);
+}
+
+static void
+_ecore_con_info_ares_nameinfo(Ecore_Con_CAres *arg, int status, int timeouts, char *node, char *service)
+{
+   switch (status)
+     {
+      case ARES_SUCCESS:
+        if (node) strcpy(arg->result->ip, node);
+        else *arg->result->ip = '\0';
+        if (service) strcpy(arg->result->service, service);
+        else *arg->result->service = '\0';
+
+        arg->done_cb(arg->data, arg->result);
+        break;
+      case ARES_ENOTIMP:
+      case ARES_ENOTFOUND:
+      case ARES_ENOMEM:
+      case ARES_EDESTRUCTION:
+      case ARES_EBADFLAGS:
+        arg->done_cb(arg->data, NULL);
+        break;
+     }
+
+   free(arg->result->info.ai_addr);
+   free(arg->result);
+   free(arg);
+}
diff --git a/src/lib/ecore_con/ecore_con_info.c b/src/lib/ecore_con/ecore_con_info.c
new file mode 100644 (file)
index 0000000..4a0ff99
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * getaddrinfo with callback
+ *
+ * man getaddrinfo
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# include <stddef.h>
+# ifdef  __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#ifdef __OpenBSD__
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "ecore_con_private.h"
+
+typedef struct _CB_Data CB_Data;
+
+struct _CB_Data
+{
+   EINA_INLIST;
+   Ecore_Con_Info_Cb cb_done;
+   void *data;
+   Ecore_Fd_Handler *fdh;
+   pid_t pid;
+   Ecore_Event_Handler *handler;
+   int fd2;
+};
+
+
+static void _ecore_con_info_readdata(CB_Data *cbdata);
+static void _ecore_con_info_slave_free(CB_Data *cbdata);
+static int _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event);
+
+static int info_init = 0;
+static CB_Data *info_slaves = NULL;
+
+int
+ecore_con_info_init(void)
+{
+   info_init++;
+   return info_init;
+}
+
+int
+ecore_con_info_shutdown(void)
+{
+   info_init--;
+   if (info_init == 0)
+     {
+       while (info_slaves) _ecore_con_info_slave_free(info_slaves);
+     }
+   return info_init;
+}
+
+int
+ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_STREAM;
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_protocol = IPPROTO_TCP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_STREAM;
+   hints.ai_flags = AI_PASSIVE;
+   hints.ai_protocol = IPPROTO_TCP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_connect(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = AI_PASSIVE;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   memset(&hints, 0, sizeof(struct addrinfo));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = 0;
+   hints.ai_protocol = IPPROTO_UDP;
+   hints.ai_canonname = NULL;
+   hints.ai_next = NULL;
+   hints.ai_addr = NULL;
+
+   return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+EAPI int
+ecore_con_info_get(Ecore_Con_Server *svr,
+                  Ecore_Con_Info_Cb done_cb,
+                  void *data,
+                  struct addrinfo *hints)
+{
+   CB_Data *cbdata;
+   int fd[2];
+
+   if (pipe(fd) < 0) return 0;
+   cbdata = calloc(1, sizeof(CB_Data));
+   if (!cbdata)
+     {
+       close(fd[0]);
+       close(fd[1]);
+       return 0;
+     }
+   cbdata->cb_done = done_cb;
+   cbdata->data = data;
+   cbdata->fd2 = fd[1];
+   if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
+                                                _ecore_con_info_data_handler,
+                                                cbdata,
+                                                NULL, NULL)))
+     {
+       free(cbdata);
+       close(fd[0]);
+       close(fd[1]);
+       return 0;
+     }
+
+   if ((cbdata->pid = fork()) == 0)
+     {
+        Ecore_Con_Info *container;
+       struct addrinfo *result = NULL;
+       char service[NI_MAXSERV];
+       char hbuf[NI_MAXHOST];
+       char sbuf[NI_MAXSERV];
+       void *tosend = NULL;
+       int tosend_len;
+       int canonname_len = 0;
+       int err;
+
+       eina_convert_itoa(svr->port, service);
+       /* CHILD */
+       if (!getaddrinfo(svr->name, service, hints, &result) && result)
+         {
+           if (result->ai_canonname)
+             canonname_len = strlen(result->ai_canonname) + 1;
+           tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen + canonname_len;
+
+           if (!(tosend = alloca(tosend_len)))
+             goto on_error;
+
+           container = (Ecore_Con_Info *)tosend;
+
+           container->size = tosend_len;
+
+           memcpy(&container->info, result, sizeof(struct addrinfo));
+           memcpy((char *)tosend + sizeof(Ecore_Con_Info), result->ai_addr, result->ai_addrlen);
+           memcpy((char *)tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen, result->ai_canonname, canonname_len);
+
+           if (!getnameinfo(result->ai_addr, result->ai_addrlen,
+                            hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+                            NI_NUMERICHOST | NI_NUMERICSERV))
+             {
+               memcpy(container->ip, hbuf, sizeof(container->ip));
+               memcpy(container->service, sbuf, sizeof(container->service));
+             }
+           err = write(fd[1], tosend, tosend_len);
+         }
+
+on_error:
+       if (result)
+         freeaddrinfo(result);
+       err = write(fd[1], "", 1);
+       close(fd[1]);
+# ifdef __USE_ISOC99
+       _Exit(0);
+# else
+       _exit(0);
+# endif
+     }
+   /* PARENT */
+   cbdata->handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler, cbdata);
+   close(fd[1]);
+   if (!cbdata->handler)
+     {
+       ecore_main_fd_handler_del(cbdata->fdh);
+       free(cbdata);
+       close(fd[0]);
+       return 0;
+     }
+   info_slaves = (CB_Data *) eina_inlist_append(EINA_INLIST_GET(info_slaves), EINA_INLIST_GET(cbdata));
+   return 1;
+}
+
+static void
+_ecore_con_info_readdata(CB_Data *cbdata)
+{
+   Ecore_Con_Info container;
+   Ecore_Con_Info *recv;
+   void *torecv;
+   int torecv_len;
+
+   ssize_t size;
+
+   size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
+              sizeof(Ecore_Con_Info));
+   if (size == sizeof(Ecore_Con_Info))
+     {
+        torecv_len = container.size;
+       torecv = malloc(torecv_len);
+
+       memcpy(torecv, &container, sizeof(Ecore_Con_Info));
+
+       size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), (char *)torecv + sizeof(Ecore_Con_Info),
+                   torecv_len - sizeof(Ecore_Con_Info));
+       if ((size > 0) && ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
+         {
+           recv = (Ecore_Con_Info *)torecv;
+
+           recv->info.ai_addr = (struct sockaddr *)((char *)torecv + sizeof(Ecore_Con_Info));
+           if ((size_t)torecv_len != (sizeof(Ecore_Con_Info) + recv->info.ai_addrlen))
+             recv->info.ai_canonname = (char *)torecv + sizeof(Ecore_Con_Info) + recv->info.ai_addrlen;
+           else
+             recv->info.ai_canonname = NULL;
+           recv->info.ai_next = NULL;
+
+           cbdata->cb_done(cbdata->data, recv);
+
+           free(torecv);
+         }
+       else
+         cbdata->cb_done(cbdata->data, NULL);
+     }
+   else
+     cbdata->cb_done(cbdata->data, NULL);
+   cbdata->cb_done = NULL;
+}
+
+static void
+_ecore_con_info_slave_free(CB_Data *cbdata)
+{
+   info_slaves = (CB_Data *) eina_inlist_remove(EINA_INLIST_GET(info_slaves), EINA_INLIST_GET(cbdata));
+   close(ecore_main_fd_handler_fd_get(cbdata->fdh));
+   ecore_main_fd_handler_del(cbdata->fdh);
+   ecore_event_handler_del(cbdata->handler);
+   free(cbdata);
+}
+
+static int
+_ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   CB_Data *cbdata;
+
+   cbdata = data;
+   if (cbdata->cb_done)
+     {
+       if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+         _ecore_con_info_readdata(cbdata);
+       else
+         {
+            cbdata->cb_done(cbdata->data, NULL);
+            cbdata->cb_done = NULL;
+         }
+     }
+   _ecore_con_info_slave_free(cbdata);
+   return 0;
+}
+
+static int
+_ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event)
+{
+   CB_Data *cbdata;
+   Ecore_Exe_Event_Del *ev;
+
+   ev = event;
+   cbdata = data;
+   if (cbdata->pid != ev->pid) return 1;
+   return 0;
+   _ecore_con_info_slave_free(cbdata);
+   return 0;
+}
diff --git a/src/lib/ecore_con/ecore_con_local.c b/src/lib/ecore_con/ecore_con_local.c
new file mode 100644 (file)
index 0000000..20cb224
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include <Ecore.h>
+#include <ecore_private.h>
+
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+
+#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
+#define LENGTH_OF_ABSTRACT_SOCKADDR_UN(s, path) (strlen(path) + 1 + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
+
+
+static int _ecore_con_local_init_count = 0;
+
+int
+ecore_con_local_init(void)
+{
+   if (++_ecore_con_local_init_count != 1)
+     return _ecore_con_local_init_count;
+
+   return _ecore_con_local_init_count;
+}
+
+int
+ecore_con_local_shutdown(void)
+{
+   if (--_ecore_con_local_init_count != 0)
+     return _ecore_con_local_init_count;
+
+   return _ecore_con_local_init_count;
+}
+
+int
+ecore_con_local_connect(Ecore_Con_Server *svr,
+                       int (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler),
+                       void *data __UNUSED__,
+                       void (*cb_free)(void *data, void *ev))
+{
+   char               buf[4096];
+   struct sockaddr_un socket_unix;
+   int                curstate = 0;
+   const char        *homedir;
+   int                socket_unix_len;
+
+   if (svr->type == ECORE_CON_LOCAL_USER)
+     {
+       homedir = getenv("HOME");
+       if (!homedir) homedir = getenv("TMP");
+       if (!homedir) homedir = "/tmp";
+       snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, svr->name, svr->port);
+     }
+   else if (svr->type == ECORE_CON_LOCAL_SYSTEM)
+     {
+       if (svr->port < 0)
+         {
+            if (svr->name[0] == '/')
+              strncpy(buf, svr->name, sizeof(buf));
+            else
+              snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s", svr->name);
+         }
+       else
+         {
+            if (svr->name[0] == '/')
+              snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
+            else
+              snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", svr->name, svr->port);
+         }
+     }
+   else if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
+     strncpy(buf, svr->name, sizeof(buf));
+
+   svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (svr->fd < 0) return 0;
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) return 0;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) return 0;
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0) return 0;
+   socket_unix.sun_family = AF_UNIX;
+
+   if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
+     {
+#ifdef HAVE_ABSTRACT_SOCKETS
+       /* copy name insto sun_path, prefixed by null to indicate abstract namespace */
+       snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s", svr->name);
+       socket_unix.sun_path[0] = '\0';
+       socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, svr->name);
+#else
+       WRN("Your system does not support abstract sockets!");
+       return 0;
+#endif
+     }
+   else
+     {
+       strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
+       socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
+     }
+
+   if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+     return 0;
+   svr->path = strdup(buf);
+   if (!svr->path) return 0;
+
+   if (svr->type & ECORE_CON_SSL)
+     ecore_con_ssl_server_init(svr);
+
+   svr->fd_handler =
+     ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                              cb_done, svr, NULL, NULL);
+   if (!svr->fd_handler) return 0;
+
+   if (!svr->delete_me)
+     {
+       /* we got our server! */
+       Ecore_Con_Event_Server_Add *e;
+
+       e = calloc(1, sizeof(Ecore_Con_Event_Server_Add));
+       if (e)
+         {
+            svr->event_count++;
+            e->server = svr;
+            ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e,
+                            cb_free, NULL);
+         }
+     }
+
+   return 1;
+}
+
+int
+ecore_con_local_listen(Ecore_Con_Server *svr,
+                      int (*cb_listen)(void *data, Ecore_Fd_Handler *fd_handler),
+                      void *data __UNUSED__)
+{
+   char               buf[4096];
+   struct sockaddr_un socket_unix;
+   struct linger      lin;
+   mode_t            pmode;
+   const char        *homedir;
+   struct stat        st;
+   mode_t             mask;
+   int                socket_unix_len;
+
+   mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
+
+   if (svr->type == ECORE_CON_LOCAL_USER)
+     {
+       homedir = getenv("HOME");
+       if (!homedir) homedir = getenv("TMP");
+       if (!homedir) homedir = "/tmp";
+       mask = S_IRUSR | S_IWUSR | S_IXUSR;
+       snprintf(buf, sizeof(buf), "%s/.ecore", homedir);
+       if (stat(buf, &st) < 0) mkdir(buf, mask);
+       snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, svr->name);
+       if (stat(buf, &st) < 0) mkdir(buf, mask);
+       snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, svr->name, svr->port);
+       mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
+     }
+   else if (svr->type == ECORE_CON_LOCAL_SYSTEM)
+     {
+       mask = 0;
+       if (svr->name[0] == '/')
+         {
+            if (svr->port >= 0)
+              snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
+            else
+              snprintf(buf, sizeof(buf), "%s", svr->name);
+         }
+       else
+         snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", svr->name, svr->port);
+     }
+   else if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
+     strncpy(buf, svr->name, sizeof(buf));
+   pmode = umask(mask);
+ start:
+   svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (svr->fd < 0) goto error_umask;
+   if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error_umask;
+   if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error_umask;
+   lin.l_onoff = 1;
+   lin.l_linger = 0;
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin, sizeof(struct linger)) < 0) goto error_umask;
+   socket_unix.sun_family = AF_UNIX;
+   if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
+     {
+#ifdef HAVE_ABSTRACT_SOCKETS
+       /* . is a placeholder */
+       snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s", svr->name);
+       /* first char null indicates abstract namespace */
+       socket_unix.sun_path[0] = '\0';
+       socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, svr->name);
+#else
+       ERR("Your system does not support abstract sockets!");
+       goto error_umask;
+#endif
+     }
+   else
+     {
+       strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
+       socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
+     }
+   if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+     {
+       if (((svr->type == ECORE_CON_LOCAL_USER) || (svr->type == ECORE_CON_LOCAL_SYSTEM)) &&
+           (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) &&
+           (unlink(buf) >= 0))
+         goto start;
+       else
+         goto error_umask;
+     }
+   if (listen(svr->fd, 4096) < 0) goto error_umask;
+   svr->path = strdup(buf);
+   if (!svr->path) goto error_umask;
+   svr->fd_handler =
+     ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+                              cb_listen, svr, NULL, NULL);
+   umask(pmode);
+   if (!svr->fd_handler) goto error;
+
+   return 1;
+
+   error_umask:
+   umask(pmode);
+   error:
+   return 0;
+}
diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h
new file mode 100644 (file)
index 0000000..ce106fa
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef _ECORE_CON_PRIVATE_H
+#define _ECORE_CON_PRIVATE_H
+
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+
+#define ECORE_MAGIC_CON_SERVER             0x77665544
+#define ECORE_MAGIC_CON_CLIENT             0x77556677
+#define ECORE_MAGIC_CON_URL                0x77074255
+
+#define ECORE_CON_TYPE 0x0f
+#define ECORE_CON_SSL  0xf0
+
+#if USE_GNUTLS
+# include <gnutls/gnutls.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
+#endif
+#ifdef HAVE_CURL
+#include <curl/curl.h>
+#endif
+
+#define READBUFSIZ 65536
+
+extern int  _ecore_con_log_dom ;
+
+#ifdef ECORE_CON_DEFAULT_LOG_COLOR
+#undef ECORE_LOG_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_CON_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_con_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_con_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_con_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_con_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_con_log_dom, __VA_ARGS__)
+
+typedef enum _Ecore_Con_State
+  {
+    ECORE_CON_CONNECTED,
+    ECORE_CON_DISCONNECTED,
+    ECORE_CON_INPROGRESS
+  } Ecore_Con_State;
+
+typedef enum _Ecore_Con_Ssl_Error
+  {
+    ECORE_CON_SSL_ERROR_NONE = 0,
+    ECORE_CON_SSL_ERROR_NOT_SUPPORTED,
+    ECORE_CON_SSL_ERROR_INIT_FAILED,
+    ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED,
+    ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED
+  } Ecore_Con_Ssl_Error;
+
+struct _Ecore_Con_Client
+{
+   ECORE_MAGIC;
+   int               fd;
+   Ecore_Con_Server *server;
+   void             *data;
+   Ecore_Fd_Handler *fd_handler;
+   int               buf_size;
+   int               buf_offset;
+   unsigned char    *buf;
+   char             *ip;
+   int               event_count;
+   struct sockaddr  *client_addr;
+   int               client_addr_len;
+#if USE_GNUTLS
+   gnutls_session    session;
+#elif USE_OPENSSL
+   SSL_CTX          *ssl_ctx;
+   SSL              *ssl;
+   int              ssl_err;
+#endif
+   char              dead : 1;
+   char              delete_me : 1;
+};
+
+struct _Ecore_Con_Server
+{
+   ECORE_MAGIC;
+   int               fd;
+   Ecore_Con_Type    type;
+   char             *name;
+   int               port;
+   char             *path;
+   void             *data;
+   Ecore_Fd_Handler *fd_handler;
+   Eina_List        *clients;
+   int               write_buf_size;
+   int               write_buf_offset;
+   unsigned char    *write_buf;
+   int               event_count;
+   int               client_limit;
+   pid_t             ppid;
+#if USE_GNUTLS
+   gnutls_session    session;
+   gnutls_anon_client_credentials_t anoncred_c;
+   gnutls_anon_server_credentials_t anoncred_s;
+#elif USE_OPENSSL
+   SSL_CTX          *ssl_ctx;
+   SSL              *ssl;
+   int              ssl_err;
+#endif
+   char             *ip;
+   char              dead : 1;
+   char              created : 1;
+   char              connecting : 1;
+   char              reject_excess_clients : 1;
+   char              delete_me : 1;
+};
+
+#ifdef HAVE_CURL
+struct _Ecore_Con_Url
+{
+   ECORE_MAGIC;
+   CURL              *curl_easy;
+   struct curl_slist *headers;
+   struct curl_httppost* post;
+   Eina_List         *additional_headers;
+   Eina_List         *response_headers;
+   char              *url;
+
+   Ecore_Con_Url_Time condition;
+   time_t             time;
+   void              *data;
+
+   Ecore_Fd_Handler  *fd_handler;
+   int               fd;
+   int               flags;
+
+   int               received;
+   int               write_fd;
+
+   unsigned char      active : 1;
+};
+#endif
+
+struct _Ecore_Con_Info
+{
+   unsigned int    size;
+   struct addrinfo info;
+   char                   ip[NI_MAXHOST];
+   char                   service[NI_MAXSERV];
+};
+
+/* from ecore_local.c */
+int ecore_con_local_init(void);
+int ecore_con_local_shutdown(void);
+int ecore_con_local_connect(Ecore_Con_Server *svr, int (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler), void *data, void (*cb_free)(void *data, void *ev));
+int ecore_con_local_listen(Ecore_Con_Server *svr, int (*cb_listen)(void *data, Ecore_Fd_Handler *fd_handler), void *data);
+/* from ecore_con_info.c */
+int ecore_con_info_init(void);
+int ecore_con_info_shutdown(void);
+int ecore_con_info_tcp_connect(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_tcp_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_udp_connect(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_udp_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_mcast_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+/* from ecore_con_ssl.c */
+Ecore_Con_Ssl_Error ecore_con_ssl_init(void);
+Ecore_Con_Ssl_Error ecore_con_ssl_shutdown(void);
+void                ecore_con_ssl_server_prepare(Ecore_Con_Server *svr);
+Ecore_Con_Ssl_Error ecore_con_ssl_server_init(Ecore_Con_Server *svr);
+Ecore_Con_Ssl_Error ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr);
+Ecore_Con_State     ecore_con_ssl_server_try(Ecore_Con_Server *svr);
+int                 ecore_con_ssl_server_read(Ecore_Con_Server *svr, unsigned char *buf, int size);
+int                 ecore_con_ssl_server_write(Ecore_Con_Server *svr, unsigned char *buf, int size);
+Ecore_Con_Ssl_Error ecore_con_ssl_client_init(Ecore_Con_Client *svr);
+Ecore_Con_Ssl_Error ecore_con_ssl_client_shutdown(Ecore_Con_Client *svr);
+Ecore_Con_State     ecore_con_ssl_client_try(Ecore_Con_Client *svr);
+int                 ecore_con_ssl_client_read(Ecore_Con_Client *svr, unsigned char *buf, int size);
+int                 ecore_con_ssl_client_write(Ecore_Con_Client *svr, unsigned char *buf, int size);
+
+
+#endif
diff --git a/src/lib/ecore_con/ecore_con_ssl.c b/src/lib/ecore_con/ecore_con_ssl.c
new file mode 100644 (file)
index 0000000..6be7214
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if USE_GNUTLS
+# include <gnutls/gnutls.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_con_private.h"
+
+static int _init_con_ssl_init_count = 0;
+
+#if USE_GNUTLS
+static int _client_connected = 0;
+
+# define SSL_SUFFIX(ssl_func) ssl_func##_gnutls
+# define _ECORE_CON_SSL_AVAILABLE 1
+
+#elif USE_OPENSSL
+# define SSL_SUFFIX(ssl_func) ssl_func##_openssl
+# define _ECORE_CON_SSL_AVAILABLE 2
+
+#else
+# define SSL_SUFFIX(ssl_func) ssl_func##_none
+# define _ECORE_CON_SSL_AVAILABLE 0
+
+#endif
+
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_init)(void);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_shutdown)(void);
+
+static void
+SSL_SUFFIX(_ecore_con_ssl_server_prepare)(Ecore_Con_Server *svr);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_server_init)(Ecore_Con_Server *svr);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_server_shutdown)(Ecore_Con_Server *svr);
+static Ecore_Con_State
+SSL_SUFFIX(_ecore_con_ssl_server_try)(Ecore_Con_Server *svr);
+static int
+SSL_SUFFIX(_ecore_con_ssl_server_read)(Ecore_Con_Server *svr, unsigned char *buf, int size);
+static int
+SSL_SUFFIX(_ecore_con_ssl_server_write)(Ecore_Con_Server *svr, unsigned char *buf, int size);
+
+static void
+SSL_SUFFIX(_ecore_con_ssl_client_prepare)(Ecore_Con_Client *cl);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_client_init)(Ecore_Con_Client *cl);
+static Ecore_Con_Ssl_Error
+SSL_SUFFIX(_ecore_con_ssl_client_shutdown)(Ecore_Con_Client *cl);
+static int
+SSL_SUFFIX(_ecore_con_ssl_client_read)(Ecore_Con_Client *cl, unsigned char *buf, int size);
+static int
+SSL_SUFFIX(_ecore_con_ssl_client_write)(Ecore_Con_Client *cl, unsigned char *buf, int size);
+
+/*
+ * General SSL API
+ */
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_init(void)
+{
+  if (!_init_con_ssl_init_count++)
+    SSL_SUFFIX(_ecore_con_ssl_init)();
+
+  return _init_con_ssl_init_count;
+}
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_shutdown(void)
+{
+  if (!--_init_con_ssl_init_count)
+    SSL_SUFFIX(_ecore_con_ssl_shutdown)();
+
+  return _init_con_ssl_init_count;
+}
+
+/**
+ * Returns if SSL support is available
+ * @return  1 if SSL is available, 0 if it is not.
+ * @ingroup Ecore_Con_Client_Group
+ */
+int
+ecore_con_ssl_available_get(void)
+{
+  return _ECORE_CON_SSL_AVAILABLE;
+}
+
+
+void
+ecore_con_ssl_server_prepare(Ecore_Con_Server *svr)
+{
+  SSL_SUFFIX(_ecore_con_ssl_server_prepare)(svr);
+}
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_server_init(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_init)(svr);
+}
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_shutdown)(svr);
+}
+
+Ecore_Con_State
+ecore_con_ssl_server_try(Ecore_Con_Server *svr)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_try)(svr);
+}
+
+int
+ecore_con_ssl_server_read(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_read)(svr, buf, size);
+}
+
+int
+ecore_con_ssl_server_write(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_server_write)(svr, buf, size);
+}
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_client_init(Ecore_Con_Client *cl)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_init)(cl);
+}
+
+Ecore_Con_Ssl_Error
+ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_shutdown)(cl);
+}
+
+int
+ecore_con_ssl_client_read(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_read)(cl, buf, size);
+}
+
+int
+ecore_con_ssl_client_write(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  return SSL_SUFFIX(_ecore_con_ssl_client_write)(cl, buf, size);
+}
+
+#if USE_GNUTLS
+
+/*
+ * GnuTLS
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_gnutls(void)
+{
+  if (gnutls_global_init())
+    return ECORE_CON_SSL_ERROR_INIT_FAILED;
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_gnutls(void)
+{
+  gnutls_global_deinit();
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr)
+{
+  svr->session = NULL;
+  svr->anoncred_c = NULL;
+  return;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
+{
+  const int *proto = NULL;
+  int ret;
+  const int kx[] = { GNUTLS_KX_ANON_DH, 0 };
+  const int ssl3_proto[] = { GNUTLS_SSL3, 0 };
+  const int tls_proto[] = {
+    GNUTLS_TLS1_0,
+    GNUTLS_TLS1_1,
+#ifdef USE_GNUTLS2
+    GNUTLS_TLS1_2,
+#endif
+    0
+  };
+
+  switch (svr->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2: /* not supported because of security issues */
+      return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
+    case ECORE_CON_USE_SSL3:
+      proto = ssl3_proto;
+      break;
+    case ECORE_CON_USE_TLS:
+      proto = tls_proto;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+
+  gnutls_anon_allocate_client_credentials(&(svr->anoncred_c));
+  gnutls_init(&(svr->session), GNUTLS_CLIENT);
+  gnutls_set_default_priority(svr->session);
+  gnutls_kx_set_priority(svr->session, kx);
+  gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c);
+  gnutls_kx_set_priority(svr->session, kx);
+  gnutls_protocol_set_priority(svr->session, proto);
+  gnutls_dh_set_prime_bits(svr->session, 512);
+
+  gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)svr->fd);
+
+  while ((ret = gnutls_handshake(svr->session)) < 0)
+    {
+      if ((ret == GNUTLS_E_AGAIN) ||
+         (ret == GNUTLS_E_INTERRUPTED))
+       continue;
+
+      _ecore_con_ssl_server_shutdown_gnutls(svr);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr)
+{
+  if (svr->session)
+    {
+      gnutls_bye(svr->session, GNUTLS_SHUT_RDWR);
+      gnutls_deinit(svr->session);
+    }
+  if (svr->anoncred_c)
+    gnutls_anon_free_client_credentials(svr->anoncred_c);
+  _ecore_con_ssl_server_prepare_gnutls(svr);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_gnutls(Ecore_Con_Server *svr __UNUSED__)
+{
+   return ECORE_CON_CONNECTED;
+}
+
+static int
+_ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_recv(svr->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static int
+_ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_send(svr->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static void
+_ecore_con_ssl_client_prepare_gnutls(Ecore_Con_Client *cl)
+{
+  cl->session = NULL;
+  if (!_client_connected)
+    cl->server->anoncred_s = NULL;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl)
+{
+  const int *proto = NULL;
+  gnutls_dh_params_t dh_params;
+  int ret;
+  const int kx[] = { GNUTLS_KX_ANON_DH, 0 };
+  const int ssl3_proto[] = { GNUTLS_SSL3, 0 };
+  const int tls_proto[] = {
+    GNUTLS_TLS1_0,
+    GNUTLS_TLS1_1,
+#ifdef USE_GNUTLS2
+    GNUTLS_TLS1_2,
+#endif
+    0
+  };
+
+  switch (cl->server->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2: /* not supported because of security issues */
+      return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
+    case ECORE_CON_USE_SSL3:
+      proto = ssl3_proto;
+      break;
+    case ECORE_CON_USE_TLS:
+      proto = tls_proto;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+
+  _client_connected++;
+  if (!cl->server->anoncred_s)
+    {
+      gnutls_anon_allocate_server_credentials(&(cl->server->anoncred_s));
+      gnutls_dh_params_init(&dh_params);
+      gnutls_dh_params_generate2(dh_params, 512);
+      gnutls_anon_set_server_dh_params(cl->server->anoncred_s, dh_params);
+    }
+
+  gnutls_init(&(cl->session), GNUTLS_SERVER);
+  gnutls_set_default_priority(cl->session);
+  gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->server->anoncred_s);
+
+  gnutls_kx_set_priority(cl->session, kx);
+
+  gnutls_protocol_set_priority(cl->session, proto);
+
+  gnutls_dh_set_prime_bits(cl->session, 512);
+
+  gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)cl->fd);
+
+  while ((ret = gnutls_handshake(cl->session)) < 0)
+    {
+      if ((ret == GNUTLS_E_AGAIN) ||
+         (ret == GNUTLS_E_INTERRUPTED))
+       continue;
+
+      _ecore_con_ssl_client_shutdown_gnutls(cl);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl)
+{
+  if (cl->session)
+    {
+      gnutls_bye(cl->session, GNUTLS_SHUT_RDWR);
+      gnutls_deinit(cl->session);
+    }
+  if (cl->server->anoncred_s && !--_client_connected)
+    gnutls_anon_free_server_credentials(cl->server->anoncred_s);
+  _ecore_con_ssl_client_prepare_gnutls(cl);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static int
+_ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_recv(cl->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+static int
+_ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  int num;
+
+  num = gnutls_record_send(cl->session, buf, size);
+  if (num > 0)
+    return num;
+  if ((num == GNUTLS_E_AGAIN) ||
+      (num == GNUTLS_E_REHANDSHAKE) ||
+      (num == GNUTLS_E_INTERRUPTED))
+    return 0;
+  return -1;
+}
+
+#elif USE_OPENSSL
+
+/*
+ * OpenSSL
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_openssl(void)
+{
+  SSL_library_init();
+  SSL_load_error_strings();
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_openssl(void)
+{
+  // FIXME nothing to do ?
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr)
+{
+  svr->ssl = NULL;
+  svr->ssl_ctx = NULL;
+  svr->ssl_err = SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr)
+{
+  switch (svr->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2:
+      /* Unsafe version of SSL */
+      if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_SSL3:
+      if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_TLS:
+      if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+  if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
+    {
+      SSL_CTX_free(svr->ssl_ctx);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  SSL_set_fd(svr->ssl, svr->fd);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr)
+{
+  if (svr->ssl)
+    {
+      if (!SSL_shutdown(svr->ssl))
+       SSL_shutdown(svr->ssl);
+      SSL_free(svr->ssl);
+    }
+  if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
+
+  _ecore_con_ssl_server_prepare_openssl(svr);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_openssl(Ecore_Con_Server *svr)
+{
+   int res, flag = 0;
+
+   if ((res = SSL_connect(svr->ssl)) == 1)
+     return ECORE_CON_CONNECTED;
+
+   svr->ssl_err = SSL_get_error(svr->ssl, res);
+
+   switch (svr->ssl_err)
+     {
+     case SSL_ERROR_NONE:
+       return ECORE_CON_CONNECTED;
+     case SSL_ERROR_WANT_READ:
+       flag = ECORE_FD_READ;
+       break;
+     case SSL_ERROR_WANT_WRITE:
+       flag = ECORE_FD_WRITE;
+       break;
+     default:
+       return ECORE_CON_DISCONNECTED;
+     }
+
+   if (svr->fd_handler && flag)
+     ecore_main_fd_handler_active_set(svr->fd_handler, flag);
+
+   return ECORE_CON_INPROGRESS;
+}
+
+static int
+_ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  int num;
+
+  num = SSL_read(svr->ssl, buf, size);
+  svr->ssl_err = SSL_get_error(svr->ssl, num);
+
+  if (svr->fd_handler)
+    {
+      if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+      else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (svr->ssl_err == SSL_ERROR_SYSCALL) ||
+      (svr->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static int
+_ecore_con_ssl_server_write_openssl(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  int num;
+
+  num = SSL_write(svr->ssl, buf, size);
+  svr->ssl_err = SSL_get_error(svr->ssl, num);
+
+  if (svr->fd_handler)
+    {
+      if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
+      else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (svr->ssl_err == SSL_ERROR_SYSCALL) ||
+      (svr->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static void
+_ecore_con_ssl_client_prepare_openssl(Ecore_Con_Client *cl)
+{
+  cl->ssl = NULL;
+  cl->ssl_ctx = NULL;
+  cl->ssl_err = SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl)
+{
+    switch (cl->server->type & ECORE_CON_SSL)
+    {
+    case ECORE_CON_USE_SSL2:
+      /* Unsafe version of SSL */
+      if (!(cl->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_SSL3:
+      if (!(cl->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    case ECORE_CON_USE_TLS:
+      if (!(cl->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+       return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+      break;
+    default:
+      return ECORE_CON_SSL_ERROR_NONE;
+    }
+  if (!(cl->ssl = SSL_new(cl->ssl_ctx)))
+    {
+      SSL_CTX_free(cl->ssl_ctx);
+      return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
+    }
+
+  SSL_set_fd(cl->ssl, cl->fd);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl)
+{
+  if (cl->ssl)
+    {
+      if (!SSL_shutdown(cl->ssl))
+       SSL_shutdown(cl->ssl);
+      SSL_free(cl->ssl);
+    }
+  if (cl->ssl_ctx) SSL_CTX_free(cl->ssl_ctx);
+
+  _ecore_con_ssl_client_prepare_openssl(cl);
+
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static int
+_ecore_con_ssl_client_read_openssl(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  int num;
+
+  num = SSL_read(cl->ssl, buf, size);
+  cl->ssl_err = SSL_get_error(cl->ssl, num);
+
+  if (cl->fd_handler)
+    {
+      if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
+      else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (cl->ssl_err == SSL_ERROR_SYSCALL) ||
+      (cl->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+static int
+_ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  int num;
+
+  num = SSL_write(cl->ssl, buf, size);
+  cl->ssl_err = SSL_get_error(cl->ssl, num);
+
+  if (cl->fd_handler)
+    {
+      if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
+      else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
+       ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
+    }
+
+  if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
+      (cl->ssl_err == SSL_ERROR_SYSCALL) ||
+      (cl->ssl_err == SSL_ERROR_SSL))
+    return -1;
+  if (num < 0)
+    return 0;
+  return num;
+}
+
+#else
+
+/*
+ * No Ssl
+ */
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_init_none(void)
+{
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_shutdown_none(void)
+{
+  return ECORE_CON_SSL_ERROR_NONE;
+}
+
+static void
+_ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr)
+{
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_init_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+/* Tries to connect an Ecore_Con_Server to an SSL host.
+ * Returns 1 on success, -1 on fatal errors and 0 if the caller
+ * should try again later.
+ */
+static Ecore_Con_State
+_ecore_con_ssl_server_try_none(Ecore_Con_Server *svr)
+{
+  return ECORE_CON_DISCONNECTED;
+}
+
+static int
+_ecore_con_ssl_server_read_none(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  return -1;
+}
+
+static int
+_ecore_con_ssl_server_write_none(Ecore_Con_Server *svr, unsigned char *buf, int size)
+{
+  return -1;
+}
+
+static void
+_ecore_con_ssl_client_prepare_none(Ecore_Con_Client *cl)
+{
+  return;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_init_none(Ecore_Con_Client *cl)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static Ecore_Con_Ssl_Error
+_ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl)
+{
+  return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
+}
+
+static int
+_ecore_con_ssl_client_read_none(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  return -1;
+}
+
+static int
+_ecore_con_ssl_client_write_none(Ecore_Con_Client *cl, unsigned char *buf, int size)
+{
+  return -1;
+}
+
+#endif
diff --git a/src/lib/ecore_con/ecore_con_url.c b/src/lib/ecore_con/ecore_con_url.c
new file mode 100644 (file)
index 0000000..4590939
--- /dev/null
@@ -0,0 +1,1302 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * For info on how to use libcurl, see:
+ * http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
+ */
+
+/*
+ * Brief usage:
+ * 1. Create an Ecore_Con_Url object
+ * 2. Register to receive the ECORE_CON_EVENT_URL_COMPLETE event
+ *    (and optionally the ECORE_CON_EVENT_URL_DATA event to receive
+ *    the response, e.g. for HTTP/FTP downloads)
+ * 3. Set the URL with ecore_con_url_url_set(...);
+ * 4. Perform the operation with ecore_con_url_send(...);
+ *
+ * Note that it is good to reuse Ecore_Con_Url objects wherever possible, but
+ * bear in mind that each one can only perform one operation at a time.
+ * You need to wait for the ECORE_CON_EVENT_URL_COMPLETE event before re-using
+ * or destroying the object.
+ *
+ * Example Usage 1 (HTTP GET):
+ *   ecore_con_url_url_set(url_con, "http://www.google.com");
+ *   ecore_con_url_send(url_con, NULL, 0, NULL);
+ *
+ * Example usage 2 (HTTP POST):
+ *   ecore_con_url_url_set(url_con, "http://www.example.com/post_handler.cgi");
+ *   ecore_con_url_send(url_con, data, data_length, "multipart/form-data");
+ *
+ * Example Usage 3 (FTP download):
+ *   ecore_con_url_url_set(url_con, "ftp://ftp.example.com/pub/myfile");
+ *   ecore_con_url_send(url_con, NULL, 0, NULL);
+ *
+ * Example Usage 4 (FTP upload as ftp://ftp.example.com/file):
+ *   ecore_con_url_url_set(url_con, "ftp://ftp.example.com");
+ *   ecore_con_url_ftp_upload(url_con, "/tmp/file", "user", "pass", NULL);
+ *
+ * Example Usage 5 (FTP upload as ftp://ftp.example.com/dir/file):
+ *   ecore_con_url_url_set(url_con, "ftp://ftp.example.com");
+ *   ecore_con_url_ftp_upload(url_con, "/tmp/file", "user", "pass","dir");
+ *
+ * FIXME: Support more CURL features: Authentication, Progress callbacks and more...
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+/**
+ * @defgroup Ecore_Con_Url_Group Ecore URL Connection Functions
+ *
+ * Utility functions that set up, use and shut down the Ecore URL
+ * Connection library.
+ * FIXME: write detailed description
+ */
+
+int ECORE_CON_EVENT_URL_DATA = 0;
+int ECORE_CON_EVENT_URL_COMPLETE = 0;
+int ECORE_CON_EVENT_URL_PROGRESS = 0;
+
+#ifdef HAVE_CURL
+static int _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_url_perform(Ecore_Con_Url *url_con);
+static size_t _ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream);
+static size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp);
+static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+static size_t _ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream);
+static void _ecore_con_event_url_free(void *data __UNUSED__, void *ev);
+static int _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match);
+static int _ecore_con_url_idler_handler(void *data __UNUSED__);
+
+static Ecore_Idler *_fd_idler_handler = NULL;
+static Eina_List *_url_con_list = NULL;
+static CURLM *curlm = NULL;
+static fd_set _current_fd_set;
+static int init_count = 0;
+static Ecore_Timer *_curl_timeout = NULL;
+
+typedef struct _Ecore_Con_Url_Event Ecore_Con_Url_Event;
+struct _Ecore_Con_Url_Event
+{
+   int type;
+   void  *ev;
+};
+
+static int
+_url_complete_idler_cb(void *data)
+{
+   Ecore_Con_Url_Event *lev;
+
+   lev = data;
+   ecore_event_add(lev->type, lev->ev, _ecore_con_event_url_free, NULL);
+   free(lev);
+
+   return 0;
+}
+
+static void
+_url_complete_push_event(int type, void *ev)
+{
+   Ecore_Con_Url_Event *lev;
+
+   lev = malloc(sizeof(Ecore_Con_Url_Event));
+   lev->type = type;
+   lev->ev = ev;
+
+   ecore_idler_add(_url_complete_idler_cb, lev);
+}
+
+#endif
+
+/**
+ * Initialises the Ecore_Con_Url library.
+ * @return Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_init(void)
+{
+#ifdef HAVE_CURL
+   init_count++;
+
+   if (init_count > 1) return init_count;
+
+   if (!ECORE_CON_EVENT_URL_DATA)
+     {
+       ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
+       ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
+       ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new();
+     }
+
+   if (!curlm)
+     {
+       long ms;
+
+       FD_ZERO(&_current_fd_set);
+       if (curl_global_init(CURL_GLOBAL_NOTHING))
+         {
+            while (_url_con_list)
+              ecore_con_url_destroy(eina_list_data_get(_url_con_list));
+            return 0;
+         }
+
+       curlm = curl_multi_init();
+       if (!curlm)
+         {
+            while (_url_con_list)
+              ecore_con_url_destroy(eina_list_data_get(_url_con_list));
+
+            init_count--;
+            return 0;
+         }
+
+       curl_multi_timeout(curlm, &ms);
+       if (ms <= 0) ms = 1000;
+
+       _curl_timeout = ecore_timer_add((double) ms / 1000, _ecore_con_url_idler_handler, (void *) 0xACE);
+       ecore_timer_freeze(_curl_timeout);
+     }
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Shuts down the Ecore_Con_Url library.
+ * @return  Number of calls that still uses Ecore_Con_Url
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_shutdown(void)
+{
+#ifdef HAVE_CURL
+   if (!init_count) return 0;
+
+   init_count--;
+
+   if (init_count != 0) return init_count;
+
+   if (_fd_idler_handler)
+     ecore_idler_del(_fd_idler_handler);
+   _fd_idler_handler = NULL;
+
+   if (_curl_timeout)
+     ecore_timer_del(_curl_timeout);
+   _curl_timeout = NULL;
+
+   while (_url_con_list)
+     ecore_con_url_destroy(eina_list_data_get(_url_con_list));
+
+   if (curlm)
+     {
+       curl_multi_cleanup(curlm);
+       curlm = NULL;
+     }
+
+   curl_global_cleanup();
+#endif
+   return 1;
+}
+
+/**
+ * Creates and initializes a new Ecore_Con_Url connection object.
+ *
+ * Creates and initializes a new Ecore_Con_Url connection object that can be
+ * uesd for sending requests.
+ *
+ * @param url URL that will receive requests. Can be changed using
+ *            ecore_con_url_url_set.
+ *
+ * @return NULL on error, a new Ecore_Con_Url on success.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_custom_new()
+ * @see ecore_con_url_url_set()
+ */
+EAPI Ecore_Con_Url *
+ecore_con_url_new(const char *url)
+{
+#ifdef HAVE_CURL
+   Ecore_Con_Url *url_con;
+
+   if (!init_count) return NULL;
+
+   url_con = calloc(1, sizeof(Ecore_Con_Url));
+   if (!url_con) return NULL;
+
+   url_con->curl_easy = curl_easy_init();
+   if (!url_con->curl_easy)
+     {
+       free(url_con);
+       return NULL;
+     }
+
+   ECORE_MAGIC_SET(url_con, ECORE_MAGIC_CON_URL);
+
+   ecore_con_url_url_set(url_con, url);
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEFUNCTION, 
+                    _ecore_con_url_data_cb);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEDATA, url_con);
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, 
+                    _ecore_con_url_progress_cb);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSDATA, url_con);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_FALSE);
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERFUNCTION, _ecore_con_url_header_cb);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERDATA, url_con);
+
+   /*
+    * FIXME: Check that these timeouts are sensible defaults
+    * FIXME: Provide a means to change these timeouts
+    */
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_CONNECTTIMEOUT, 30);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEOUT, 300);
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_FOLLOWLOCATION, 1);
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate");
+
+   url_con->fd = -1;
+   url_con->write_fd = -1;
+   url_con->additional_headers = NULL;
+   url_con->response_headers = NULL;
+
+   return url_con;
+#else
+   return NULL;
+   url = NULL;
+#endif
+}
+
+/**
+ * Creates a custom connection object.
+ *
+ * Creates and initializes a new Ecore_Con_Url for a custom request (e.g. HEAD,
+ * SUBSCRIBE and other obscure HTTP requests). This object should be used like
+ * one created with ecore_con_url_new().
+ *
+ * @param url URL that will receive requests
+ * @param custom_request Custom request (e.g. GET, POST, HEAD, PUT, etc)
+ *
+ * @return NULL on error, a new Ecore_Con_Url on success.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_new()
+ * @see ecore_con_url_url_set()
+ */
+EAPI Ecore_Con_Url *
+ecore_con_url_custom_new(const char *url, const char *custom_request)
+{
+#ifdef HAVE_CURL
+   Ecore_Con_Url *url_con;
+
+   if (!url) return NULL;
+   if (!custom_request) return NULL;
+
+   url_con = ecore_con_url_new(url);
+
+   if (!url_con) return NULL;
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_CUSTOMREQUEST, custom_request);
+
+   return url_con;
+#else
+   return NULL;
+   url = NULL;
+   custom_request = NULL;
+#endif
+}
+
+/**
+ * Destroys a Ecore_Con_Url connection object.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_new()
+ */
+EAPI void
+ecore_con_url_destroy(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+   char *s;
+
+   if (!url_con) return;
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_destroy");
+       return;
+     }
+
+   ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
+   if(url_con->fd != -1)
+     {
+       FD_CLR(url_con->fd, &_current_fd_set);
+       if (url_con->fd_handler)
+         ecore_main_fd_handler_del(url_con->fd_handler);
+       url_con->fd = -1;
+       url_con->fd_handler = NULL;
+     }
+
+   if (url_con->post)
+     curl_formfree(url_con->post);
+   url_con->post = NULL;
+   
+   if (url_con->curl_easy)
+     {
+       // FIXME: For an unknown reason, progress continue to arrive after destruction
+       // this prevent any further call to the callback.
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL);
+
+       if (url_con->active)
+         {
+            url_con->active = 0;
+
+            curl_multi_remove_handle(curlm, url_con->curl_easy);
+         }
+       curl_easy_cleanup(url_con->curl_easy);
+     }
+   _url_con_list = eina_list_remove(_url_con_list, url_con);
+   curl_slist_free_all(url_con->headers);
+   EINA_LIST_FREE(url_con->additional_headers, s)
+     free(s);
+   EINA_LIST_FREE(url_con->response_headers, s)
+     free(s);
+   free(url_con->url);
+   free(url_con);
+#else
+   return;
+   url_con = NULL;
+#endif
+}
+
+/**
+ * Sets the URL to send the request to.
+ *
+ * @param url_con Connection object through which the request will be sent.
+ * @param url URL that will receive the request
+ *
+ * @return 1 on success, 0 on error.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_url_set");
+       return 0;
+     }
+
+   if (url_con->active) return 0;
+
+   if (url_con->url) free(url_con->url);
+   url_con->url = NULL;
+   if (url) url_con->url = strdup(url);
+   if (url_con->url)
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, url_con->url);
+   else
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, "");
+   return 1;
+#else
+   return 0;
+   url_con = NULL;
+   url = NULL;
+#endif
+}
+
+/**
+ * Associates data with a connection object.
+ *
+ * Associates data with a connection object, which can be retrieved later with
+ * ecore_con_url_data_get()).
+ *
+ * @param url_con Connection object to associate data.
+ * @param data Data to be set.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_data_get()
+ */
+EAPI void
+ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_set");
+       return;
+     }
+
+   url_con->data = data;
+#else
+   return;
+   url_con = NULL;
+   data = NULL;
+#endif
+}
+
+/**
+ * Adds an additional header to the request connection object.
+ *
+ * Adds an additional header to the request connection object. This addition
+ * will be valid for only one ecore_con_url_send() call.
+ *
+ * @param url_con Connection object
+ * @param key Header key
+ * @param value Header value
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_send()
+ * @see ecore_con_url_additional_headers_clear()
+ */
+EAPI void
+ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, const char *key, const char *value)
+{
+#ifdef HAVE_CURL
+   char *tmp;
+
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_additional_header_add");
+       return;
+     }
+
+   tmp = malloc(strlen(key) + strlen(value) + 3);
+   if (!tmp) return ;
+   sprintf(tmp, "%s: %s", key, value);
+   url_con->additional_headers = eina_list_append(url_con->additional_headers, tmp);
+#else
+   return;
+   url_con = NULL;
+   key = NULL;
+   value = NULL;
+#endif
+}
+
+/*
+ * Cleans additional headers.
+ *
+ * Cleans additional headers associated with a connection object (previously
+ * added with ecore_con_url_additional_header_add()).
+ *
+ * @param url_con Connection object to clean additional headers.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_additional_header_add()
+ * @see ecore_con_url_send()
+ */
+EAPI void
+ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+   char *s;
+
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_additional_headers_clear");
+       return;
+     }
+
+   EINA_LIST_FREE(url_con->additional_headers, s)
+     free(s);
+#else
+   return;
+   url_con = NULL;
+#endif
+}
+
+/**
+ * Retrieves data associated with a Ecore_Con_Url connection object.
+ *
+ * Retrieves data associated with a Ecore_Con_Url connection object (previously
+ * set with ecore_con_url_data_set()).
+ *
+ * @param Connection object to retrieve data from.
+ *
+ * @return Data associated with the given object.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_data_set()
+ */
+EAPI void *
+ecore_con_url_data_get(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_get");
+       return NULL;
+     }
+
+   return url_con->data;
+#else
+   return NULL;
+   url_con = NULL;
+#endif
+}
+
+/**
+ * FIXME: To be documented.
+ * @return  FIXME: To be documented.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI void
+ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t tm)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_time");
+       return;
+     }
+
+   url_con->condition = condition;
+   url_con->time = tm;
+#else
+   return;
+   url_con = NULL;
+   condition = 0;
+   tm = 0;
+#endif
+}
+
+/**
+ * Setup a file for receiving request data.
+ *
+ * Setups a file to have response data written into. Note that
+ * ECORE_CON_EVENT_URL_DATA events will not be emitted if a file has been set to
+ * receive the response data.
+ *
+ * @param url_con Connection object to set file
+ * @param fd File descriptor associated with the file
+ *
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI void
+ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_set");
+       return ;
+     }
+   url_con->write_fd = fd;
+#endif
+}
+
+/**
+ * Retrieves the number of bytes received.
+ *
+ * Retrieves the number of bytes received on the last request of the given
+ * connection object.
+ *
+ * @param url_con Connection object which the request was sent on.
+ *
+ * @return Number of bytes received on request.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_send()
+ */
+EAPI int
+ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_received_bytes_get");
+       return -1;
+     }
+
+   return url_con->received;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Retrieves headers from last request sent.
+ *
+ * Retrieves a list containing the response headers. This function should be
+ * used after an ECORE_CON_EVENT_URL_COMPLETE event (headers should normally be
+ * ready at that time).
+ *
+ * @param url_con Connection object to retrieve response headers from.
+ *
+ * @return List of response headers. This list must not be modified by the user.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI const Eina_List *
+ecore_con_url_response_headers_get(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+   return url_con->response_headers;
+#else
+   return NULL;
+#endif
+}
+
+/**
+ * Sets url_con to use http auth, with given username and password, "safely" or not.
+ *
+ * @param url_con Connection object to perform a request on, previously created
+ *               with ecore_con_url_new() or ecore_con_url_custom_new().
+ * @param username Username to use in authentication
+ * @param password Password to use in authentication
+ * @param safe Whether to use "safer" methods (eg, NOT http basic auth)
+ *
+ * @return 1 on success, 0 on error.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_httpauth_set(Ecore_Con_Url *url_con, const char *username, const char *password, Eina_Bool safe)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_httpauth_set");
+       return 0;
+     }
+# ifdef CURLOPT_USERNAME
+#  ifdef CURLOPT_PASSWORD   
+   if ((username != NULL) && (password != NULL))
+     {
+       if (safe)
+          curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
+       else
+          curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_USERNAME, username);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_PASSWORD, password);
+        return 1;
+     }
+#  endif
+# endif
+#endif
+   return 0;
+}
+
+/**
+ * Sends a request.
+ *
+ * @param url_con Connection object to perform a request on, previously created
+ *                with ecore_con_url_new() or ecore_con_url_custom_new().
+ * @param data Payload (data sent on the request)
+ * @param length  Payload length
+ * @param content_type Content type of the payload (e.g. text/xml)
+ *
+ * @return 1 on success, 0 on error.
+ *
+ * @ingroup Ecore_Con_Url_Group
+ *
+ * @see ecore_con_url_custom_new()
+ * @see ecore_con_url_additional_headers_clear()
+ * @see ecore_con_url_additional_header_add()
+ * @see ecore_con_url_data_set()
+ * @see ecore_con_url_data_get()
+ * @see ecore_con_url_response_headers_get()
+ */
+EAPI int
+ecore_con_url_send(Ecore_Con_Url *url_con, const void *data, size_t length, const char *content_type)
+{
+#ifdef HAVE_CURL
+   Eina_List *l;
+   const char *s;
+   char tmp[256];
+
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_send");
+       return 0;
+     }
+
+   if (url_con->active) return 0;
+   if (!url_con->url) return 0;
+
+   /* Free response headers from previous send() calls */
+   EINA_LIST_FREE(url_con->response_headers, s) free((char *)s);
+   url_con->response_headers = NULL;
+
+   curl_slist_free_all(url_con->headers);
+   url_con->headers = NULL;
+
+   if (data)
+     {
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, data);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length);
+
+       if (content_type && (strlen(content_type) < 200))
+         {
+            sprintf(tmp, "Content-type: %s", content_type);
+            url_con->headers = curl_slist_append(url_con->headers, tmp);
+         }
+       sprintf(tmp, "Content-length: %zu", length);
+       url_con->headers = curl_slist_append(url_con->headers, tmp);
+     }
+
+   switch (url_con->condition)
+     {
+      case ECORE_CON_URL_TIME_NONE:
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, 
+                          CURL_TIMECOND_NONE);
+        break;
+      case ECORE_CON_URL_TIME_IFMODSINCE:
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, 
+                          CURL_TIMECOND_IFMODSINCE);
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+        break;
+      case ECORE_CON_URL_TIME_IFUNMODSINCE:
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, 
+                          CURL_TIMECOND_IFUNMODSINCE);
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+        break;
+      case ECORE_CON_URL_TIME_LASTMOD:
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, 
+                          CURL_TIMECOND_LASTMOD);
+        curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+        break;
+     }
+
+   /* Additional headers */
+   EINA_LIST_FOREACH(url_con->additional_headers, l, s)
+     url_con->headers = curl_slist_append(url_con->headers, s);
+
+   curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPHEADER, url_con->headers);
+
+   url_con->received = 0;
+
+   int res = _ecore_con_url_perform(url_con);
+
+   return res;
+#else
+   return 0;
+   url_con = NULL;
+   data = NULL;
+   length = 0;
+   content_type = NULL;
+#endif
+}
+
+/**
+ * Makes a FTP upload
+ * @return  FIXME: To be more documented.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, const char *filename, const char *user, const char *pass, const char *upload_dir)
+{
+#ifdef HAVE_CURL
+   char url[4096];
+   char userpwd[4096];
+   FILE *fd;
+   struct stat file_info;
+
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ftp_upload");
+       return 0;
+     }
+
+   if (url_con->active) return 0;
+   if (!url_con->url) return 0;
+   if (filename)
+     {
+       char tmp[PATH_MAX];
+
+       snprintf(tmp, PATH_MAX, "%s", filename);
+
+       if (stat(filename, &file_info)) return 0;
+       fd = fopen(filename, "rb");
+       if (upload_dir)
+          snprintf(url, sizeof(url), "ftp://%s/%s/%s", url_con->url, 
+                    upload_dir, basename(tmp));
+       else
+          snprintf(url, sizeof(url), "ftp://%s/%s", url_con->url, 
+                    basename(tmp));
+       snprintf(userpwd, sizeof(userpwd), "%s:%s", user, pass);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_INFILESIZE_LARGE, 
+                         (curl_off_t)file_info.st_size);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_USERPWD, userpwd);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_UPLOAD, 1);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_READFUNCTION, 
+                         _ecore_con_url_read_cb);
+       curl_easy_setopt(url_con->curl_easy, CURLOPT_READDATA, fd);
+       ecore_con_url_url_set(url_con, url);
+
+       return _ecore_con_url_perform(url_con);
+     }
+   else
+     return 0;
+#else
+   return 0;
+   url_con = NULL;
+   filename = NULL;
+   user = NULL;
+   pass = NULL;
+   upload_dir = NULL;
+#endif
+}
+
+/**
+ * Send a Curl httppost 
+ * @return 1 on success, 0 on error.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI int
+ecore_con_url_http_post_send(Ecore_Con_Url *url_con, void *httppost)
+{
+#ifdef HAVE_CURL
+  if (url_con->post)
+    curl_formfree(url_con->post);
+  url_con->post = NULL;
+
+  if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+    {
+      ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_http_post_send");
+      return 0;
+    }
+
+  url_con->post = httppost;
+  
+  if (url_con->active) return 0;
+  if (!url_con->url) return 0;  
+  
+  curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPPOST, httppost);
+  
+  return ecore_con_url_send(url_con, NULL, 0, NULL);
+#else
+  return 0;
+  url_con = NULL;
+#endif
+}
+
+/**
+ * Enable or disable libcurl verbose output, useful for debug
+ * @return  FIXME: To be more documented.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI void
+ecore_con_url_verbose_set(Ecore_Con_Url *url_con, int verbose)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_verbose_set");
+       return;
+     }
+
+   if (url_con->active) return;
+   if (!url_con->url) return;
+   if (verbose == EINA_TRUE)
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, 1);
+   else
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, 0);
+#endif
+}
+
+/**
+ * Enable or disable EPSV extension
+ * @return  FIXME: To be more documented.
+ * @ingroup Ecore_Con_Url_Group
+ */
+EAPI void
+ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, int use_epsv)
+{
+#ifdef HAVE_CURL
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ftp_use_epsv_set");
+       return;
+     }
+
+   if (url_con->active) return;
+   if (!url_con->url) return;
+   if (use_epsv == EINA_TRUE)
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, 1);
+   else
+     curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, 0);
+#endif
+}
+
+#ifdef HAVE_CURL
+static int
+_ecore_con_url_suspend_fd_handler(void)
+{
+   Eina_List *l;
+   Ecore_Con_Url *url_con;
+   int deleted = 0;
+
+   if (!_url_con_list) return 0;
+
+   EINA_LIST_FOREACH(_url_con_list, l, url_con)
+     {
+       if (url_con->active && url_con->fd_handler)
+         {
+            ecore_main_fd_handler_del(url_con->fd_handler);
+            url_con->fd_handler = NULL;
+            deleted++;
+         }
+     }
+
+   return deleted;
+}
+
+static int
+_ecore_con_url_restart_fd_handler(void)
+{
+   Eina_List *l;
+   Ecore_Con_Url *url_con;
+   int activated = 0;
+
+   if (!_url_con_list) return 0;
+
+   EINA_LIST_FOREACH(_url_con_list, l, url_con)
+     {
+       if (url_con->fd_handler == NULL && url_con->fd != -1)
+         {
+            url_con->fd_handler = 
+               ecore_main_fd_handler_add(url_con->fd, url_con->flags,
+                                         _ecore_con_url_fd_handler,
+                                         NULL, NULL, NULL);
+            activated++;
+         }
+     }
+
+   return activated;
+}
+
+static size_t
+_ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp)
+{
+   Ecore_Con_Url *url_con;
+   Ecore_Con_Event_Url_Data *e;
+   size_t real_size = size * nitems;
+
+   url_con = (Ecore_Con_Url *)userp;
+
+   if (!url_con) return -1;
+   if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+     {
+       ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_cb");
+       return -1;
+     }
+
+   url_con->received += real_size;
+
+   if (url_con->write_fd < 0)
+     {
+       e = malloc(sizeof(Ecore_Con_Event_Url_Data) + sizeof(unsigned char) * (real_size - 1));
+       if (e)
+         {
+            e->url_con = url_con;
+            e->size = real_size;
+            memcpy(e->data, buffer, real_size);
+            ecore_event_add(ECORE_CON_EVENT_URL_DATA, e,
+                            _ecore_con_event_url_free, NULL);
+         }
+     }
+   else
+     {
+       ssize_t count = 0;
+       size_t total_size = real_size;
+       size_t offset = 0;
+
+       while (total_size > 0)
+         {
+            count = write(url_con->write_fd, (char*) buffer + offset, total_size);
+            if (count < 0)
+              {
+                 if (errno != EAGAIN && errno != EINTR) return -1;
+              }
+            else
+              {
+                 total_size -= count;
+                 offset += count;
+              }
+         }
+     }
+
+   return real_size;
+}
+
+#define ECORE_CON_URL_TRANSMISSION(Transmit, Event, Url_con, Total, Now) \
+{ \
+   Ecore_Con_Event_Url_Progress *e; \
+   if ((Total != 0) || (Now != 0)) \
+     { \
+       e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress)); \
+       if (e) \
+         { \
+            e->url_con = url_con; \
+            e->total = Total; \
+            e->now = Now; \
+            ecore_event_add(Event, e, _ecore_con_event_url_free, NULL); \
+         } \
+     } \
+}
+
+static size_t
+_ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream)
+{
+   size_t real_size = size * nitems;
+   Ecore_Con_Url *url_con = stream;
+
+   char *header = malloc(sizeof(char)*(real_size + 1));
+   if (!header) return real_size;
+   memcpy(header, ptr, real_size);
+   header[real_size] = '\0';
+
+   url_con->response_headers = eina_list_append(url_con->response_headers,
+                                               header);
+
+   return real_size;
+}
+
+static int
+_ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+   Ecore_Con_Event_Url_Progress        *e;
+   Ecore_Con_Url *url_con;
+
+   url_con = clientp;
+
+   e = malloc(sizeof(Ecore_Con_Event_Url_Progress));
+   if (e)
+     {
+       e->url_con = url_con;
+       e->down.total = dltotal;
+       e->down.now = dlnow;
+       e->up.total = ultotal;
+       e->up.now = ulnow;
+       ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, 
+                        _ecore_con_event_url_free, NULL);
+     }
+
+   return 0;
+}
+
+static size_t
+_ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream)
+{
+   size_t retcode = fread(ptr, size, nitems, stream);
+
+   if (ferror((FILE*)stream)) 
+     {
+        fclose(stream);
+        return CURL_READFUNC_ABORT;
+     } 
+   else if ((retcode == 0) || (retcode < nitems)) 
+     {
+        fclose((FILE*)stream);
+        return 0;
+     }
+   INF("*** We read %zu bytes from file", retcode);
+   return retcode;
+}
+
+static int
+_ecore_con_url_perform(Ecore_Con_Url *url_con)
+{
+   fd_set read_set, write_set, exc_set;
+   int fd_max, fd;
+   int flags, still_running;
+   int completed_immediately = 0;
+
+   _url_con_list = eina_list_append(_url_con_list, url_con);
+
+   url_con->active = 1;
+   curl_multi_add_handle(curlm, url_con->curl_easy);
+   /* This one can't be stopped, or the download never start. */
+   while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM);
+
+   completed_immediately = _ecore_con_url_process_completed_jobs(url_con);
+
+   if (!completed_immediately)
+     {
+       if (url_con->fd_handler)
+         ecore_main_fd_handler_del(url_con->fd_handler);
+       url_con->fd_handler = NULL;
+
+       /* url_con still active -- set up an fd_handler */
+       FD_ZERO(&read_set);
+       FD_ZERO(&write_set);
+       FD_ZERO(&exc_set);
+
+       /* Stupid curl, why can't I get the fd to the current added job? */
+       curl_multi_fdset(curlm, &read_set, &write_set, &exc_set, &fd_max);
+       for (fd = 0; fd <= fd_max; fd++)
+         {
+            if (!FD_ISSET(fd, &_current_fd_set))
+              {
+                 flags = 0;
+                 if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ;
+                 if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE;
+                 if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR;
+                 if (flags)
+                   {
+                      long ms = 0;
+
+                      curl_multi_timeout(curlm, &ms);
+                      if (ms == 0) ms = 1000;
+
+                      FD_SET(fd, &_current_fd_set);
+                      url_con->fd = fd;
+                      url_con->flags = flags;
+                      url_con->fd_handler = 
+                         ecore_main_fd_handler_add(fd, flags, 
+                                                   _ecore_con_url_fd_handler,
+                                                   NULL, NULL, NULL);
+                      break;
+                   }
+              }
+         }
+       if (!url_con->fd_handler)
+         {
+            /* Failed to set up an fd_handler */
+            ecore_timer_freeze(_curl_timeout);
+            curl_multi_remove_handle(curlm, url_con->curl_easy);
+            url_con->active = 0;
+            url_con->fd = -1;
+            return 0;
+         }
+       ecore_timer_thaw(_curl_timeout);
+     }
+
+   return 1;
+}
+
+static int
+_ecore_con_url_idler_handler(void *data)
+{
+   double start;
+   int done = 1, still_running;
+
+   start = ecore_time_get();
+   while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM)
+     /* make this not more than a frametime to keep interactivity high */
+     if ((ecore_time_get() - start) > ecore_animator_frametime_get())
+       {
+         done = 0;
+         break;
+       }
+
+   _ecore_con_url_process_completed_jobs(NULL);
+
+   if (done)
+     {
+       _ecore_con_url_restart_fd_handler();
+       _fd_idler_handler = NULL;
+
+       if (!_url_con_list)
+         ecore_timer_freeze(_curl_timeout);
+       return data == (void*) 0xACE ? 1 : 0;
+     }
+
+   return 1;
+}
+
+static int
+_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   _ecore_con_url_suspend_fd_handler();
+
+   if (_fd_idler_handler == NULL)
+     _fd_idler_handler = ecore_idler_add(_ecore_con_url_idler_handler, NULL);
+
+   return 1;
+}
+
+static int
+_ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match)
+{
+   Eina_List *l;
+   Ecore_Con_Url *url_con;
+   Ecore_Con_Event_Url_Complete *e;
+   CURLMsg *curlmsg;
+   int n_remaining;
+   int job_matched = 0;
+
+   /* Loop jobs and check if any are done */
+   while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL)
+     {
+       if (curlmsg->msg != CURLMSG_DONE) continue;
+
+       /* find the job which is done */
+       EINA_LIST_FOREACH(_url_con_list, l, url_con)
+         {
+            if (curlmsg->easy_handle == url_con->curl_easy)
+              {
+                 if (url_con_to_match && (url_con == url_con_to_match))
+                    job_matched = 1;
+                 if(url_con->fd != -1)
+                   {
+                      FD_CLR(url_con->fd, &_current_fd_set);
+                      if (url_con->fd_handler)
+                        ecore_main_fd_handler_del(url_con->fd_handler);
+                      url_con->fd = -1;
+                      url_con->fd_handler = NULL;
+                   }
+                 _url_con_list = eina_list_remove(_url_con_list, url_con);
+                 url_con->active = 0;
+                 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
+                 if (e)
+                   {
+                      e->url_con = url_con;
+                      e->status = 0;
+                      if (curlmsg->data.result == CURLE_OK)
+                        {
+                           long status;        /* curl API uses long, not int */
+
+                           status = 0;
+                           curl_easy_getinfo(curlmsg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
+                           e->status = status;
+                        }
+
+                      _url_complete_push_event(ECORE_CON_EVENT_URL_COMPLETE, e);
+                   }
+                 curl_multi_remove_handle(curlm, url_con->curl_easy);
+                 break;
+              }
+         }
+     }
+
+   return job_matched;
+}
+
+static void
+_ecore_con_event_url_free(void *data __UNUSED__, void *ev)
+{
+   free(ev);
+}
+
+#endif
diff --git a/src/lib/ecore_config/.cvsignore b/src/lib/ecore_config/.cvsignore
new file mode 100644 (file)
index 0000000..59bc827
--- /dev/null
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_config.la
+ecore_config_ipc_ecore.la
+system.db
diff --git a/src/lib/ecore_config/Ecore_Config.h b/src/lib/ecore_config/Ecore_Config.h
new file mode 100644 (file)
index 0000000..6733d7b
--- /dev/null
@@ -0,0 +1,312 @@
+#ifndef _ECORE_CONFIG_H
+# define _ECORE_CONFIG_H
+
+#ifdef EAPI
+#undef EAPI
+#endif
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+/**
+ * @file 
+ * @brief Provides the Enlightened Property Library.
+ *
+ * This file provies all headers and structs for use with Ecore_Config.
+ * Using individual header files should not be necessary.
+ */
+
+# define DIR_DELIMITER      '/'
+# define ECORE_CONFIG_FLOAT_PRECISION 1000
+
+/* FIXME: this should only be included if evas is present */
+# include <Evas.h>
+
+# define ECORE_CONFIG_GLOBAL_ID "_system"
+
+/* structures */
+
+/**
+ * Valid configuration property types.
+ */
+typedef enum Ecore_Config_Type
+{
+   ECORE_CONFIG_NIL = 0,                       /**< Property with no value. */
+   ECORE_CONFIG_INT = 1,                       /**< Integer property type. */
+   ECORE_CONFIG_FLT = 2,                       /**< Float property type. */
+   ECORE_CONFIG_STR = 3,                       /**< String property type. */
+   ECORE_CONFIG_RGB = 4,                       /**< Colour property type. */
+   ECORE_CONFIG_THM = 5,                       /**< Theme property type. */
+   ECORE_CONFIG_BLN = 6,                       /**< Boolean property type. */
+   ECORE_CONFIG_SCT = 7,      /**< Structure property type */
+} Ecore_Config_Type;
+
+typedef enum Ecore_Config_Flag
+{
+   ECORE_CONFIG_FLAG_NONE = 0,
+   ECORE_CONFIG_FLAG_BOUNDS = 1,
+   ECORE_CONFIG_FLAG_MODIFIED = 2,
+   ECORE_CONFIG_FLAG_SYSTEM = 4,
+   ECORE_CONFIG_FLAG_CMDLN = 8
+} Ecore_Config_Flag;
+
+/**
+ * Property change callback function prototype.
+ */
+typedef int         (*Ecore_Config_Listener) (const char *key,
+                                             const Ecore_Config_Type type,
+                                             const int tag, void *data);
+
+typedef struct Ecore_Config_Listener_List
+{
+   Ecore_Config_Listener listener;
+   const char         *name;
+   void               *data;
+   int                 tag;
+   struct Ecore_Config_Listener_List *next;
+} Ecore_Config_Listener_List;
+
+/**
+ * The actual property for storing a key-value pair.
+ */
+typedef struct Ecore_Config_Prop
+{
+   char               *key;    /* Property key. */
+   char               *description;    /* Description set by ecore_config_descibe. */
+   char                short_opt;      /* short identifier on command line (-f) */
+   char               *long_opt;       /* long identifier on command line (--foo) */
+   char               *ptr;    /* Used as the value when the property is a string or theme. */
+   Ecore_Config_Type   type;   /* Property type. */
+   long                val;    /* Used as the value when the property is an integer, float or colour. */
+   long                lo;     /* Lower bound for the value when the property is an integer or float. */
+   long                hi;     /* Higher bound for the value when the property is an integer or float. */
+   long                step;   /* Increment for the value when the property is an integer or float. */
+   Ecore_Config_Flag   flags;  /// < Configuration flags.
+   Ecore_Config_Listener_List *listeners;      /* List of change listeners. */
+   void               *data;   /// < Stores extra data for the property.
+   struct Ecore_Config_Prop *parent; /* if we are in a struct we have a parent to notify of changes etc */
+   struct Ecore_Config_Prop *next;     /* Pointer to the next property in the list. */
+} Ecore_Config_Prop;
+
+/*
+ * A container for a list of properties.  Provided so that an
+ * application can use different set of properties at any time. This
+ * is useful for multiple window support.
+ */
+typedef struct Ecore_Config_Bundle
+{
+   char               *identifier;     /* Identifier for this set of properties (window ID for example) */
+   char               *owner;  /* This is used to store the application name related to the bundle */
+   long                serial; /* Unique identifier to identify bundle */
+   Ecore_Config_Prop  *data;   /* Pointer to root of property list */
+   void               *user_data;      /* App specific pointer to "other data" */
+   struct Ecore_Config_Bundle *next;   /* Pointer to next bundle in this application */
+} Ecore_Config_Bundle;
+
+typedef struct Ecore_Config_Server
+{
+   void               *server;
+   char               *name;
+   Ecore_Config_Bundle *bundles;       /* data anchor */
+   struct Ecore_Config_Server *next;
+} Ecore_Config_Server;
+
+# ifdef __cplusplus
+extern              "C"
+{
+# endif
+
+/* global ptrs to save passing them through the API */
+   EAPI extern Ecore_Config_Server *__ecore_config_server_global;
+   EAPI extern Ecore_Config_Server *__ecore_config_server_local;
+   EAPI extern Ecore_Config_Bundle *__ecore_config_bundle_local;
+   EAPI extern char        *__ecore_config_app_name;
+
+   EAPI Ecore_Config_Prop  *ecore_config_get(const char *key);
+   EAPI const char         *ecore_config_type_get(const Ecore_Config_Prop *e);
+   EAPI int                 ecore_config_boolean_get(const char *key);
+   EAPI char               *ecore_config_string_get(const char *key);
+   EAPI long                ecore_config_int_get(const char *key);
+   EAPI int                 ecore_config_argb_get(const char *key, int *a, int *r,
+                                                 int *g, int *b);
+   EAPI long                ecore_config_argbint_get(const char *key);
+   EAPI char               *ecore_config_argbstr_get(const char *key);
+   EAPI float               ecore_config_float_get(const char *key);
+   EAPI char               *ecore_config_theme_get(const char *key);
+   EAPI char               *ecore_config_as_string_get(const char *key);
+   EAPI int                 ecore_config_bound(Ecore_Config_Prop *e);
+   EAPI int                 ecore_config_describe(const char *key, const char *desc);
+   EAPI int                 ecore_config_short_opt_set(const char *key,
+                                                      char short_opt);
+   EAPI int                 ecore_config_long_opt_set(const char *key,
+                                                     const char *long_opt);
+   EAPI int                 ecore_config_set(const char *key, const char *val);
+   EAPI int                 ecore_config_typed_set(const char *key, const void *val,
+                                                  int type);
+   EAPI int                 ecore_config_boolean_set(const char *key, int val);
+   EAPI int                 ecore_config_string_set(const char *key, const char *val);
+   EAPI int                 ecore_config_int_set(const char *key, int val);
+   EAPI int                 ecore_config_argb_set(const char *key, int a, int r, int g, int b);
+   EAPI int                 ecore_config_argbint_set(const char *key, long argb);
+   EAPI int                 ecore_config_argbstr_set(const char *key, const char *val);
+   EAPI int                 ecore_config_float_set(const char *key, float val);
+   EAPI int                 ecore_config_theme_set(const char *key, const char *val);
+   EAPI int                 ecore_config_theme_preview_group_set(const char *key,
+                                                                const char *group);
+   EAPI int                 ecore_config_as_string_set(const char *key, const char *val);
+
+   EAPI int                 ecore_config_default(const char *key, const char *val,
+                                                float lo, float hi, float step);
+   EAPI int                 ecore_config_typed_default(const char *key, const void *val,
+                                                      int type);
+   EAPI int                 ecore_config_boolean_default(const char *key, int val);
+   EAPI int                 ecore_config_int_default(const char *key, int val);
+   EAPI int                 ecore_config_int_default_bound(const char *key, int val,
+                                                          int lo, int hi, int step);
+   EAPI int                 ecore_config_string_default(const char *key, const char *val);
+   EAPI int                 ecore_config_float_default(const char *key, float val);
+   EAPI int                 ecore_config_float_default_bound(const char *key,
+                                                            float val, float lo,
+                                                            float hi, float step);
+   EAPI int                 ecore_config_argb_default(const char *key, int a, int r, int g, int b);
+   EAPI int                 ecore_config_argbint_default(const char *key, long argb);
+   EAPI int                 ecore_config_argbstr_default(const char *key, const char *val);
+   EAPI int                 ecore_config_theme_default(const char *key, const char *val);
+   EAPI int                 ecore_config_struct_default(const char *key);
+   EAPI int                 ecore_config_struct_int_add(const char *key, const char *name, int val);
+   EAPI int                 ecore_config_struct_float_add(const char *key, const char *name, float val);
+   EAPI int                 ecore_config_struct_create(const char *key);
+   EAPI int                 ecore_config_struct_string_add(const char *key, const char *name, const char* val);
+   EAPI int                 ecore_config_struct_theme_add(const char *key, const char *name, const char* val);
+   EAPI int                 ecore_config_struct_argb_add(const char *key, const char *name, int a, int r, int g, int b);
+   EAPI int                 ecore_config_struct_boolean_add(const char *key, const char *name, int val);
+   EAPI int                 ecore_config_struct_get(const char *key, void *data);
+
+   EAPI int                 ecore_config_listen(const char *name, const char *key,
+                                               Ecore_Config_Listener listener,
+                                               int tag, void *data);
+   EAPI int                 ecore_config_deaf(const char *name, const char *key,
+                                             Ecore_Config_Listener listener);
+   EAPI Ecore_Config_Prop  *ecore_config_dst(Ecore_Config_Prop *e);
+   EAPI int                 ecore_config_type_guess(const char *key, const char *val);
+
+   EAPI Ecore_Config_Bundle *ecore_config_bundle_new(Ecore_Config_Server *srv,
+                                                    const char *id);
+   EAPI Ecore_Config_Bundle *ecore_config_bundle_1st_get(Ecore_Config_Server *srv);
+   EAPI Ecore_Config_Bundle *ecore_config_bundle_next_get(Ecore_Config_Bundle *ns);
+   EAPI Ecore_Config_Bundle *ecore_config_bundle_by_serial_get(Ecore_Config_Server *srv,
+                                                              long serial);
+   EAPI Ecore_Config_Bundle *ecore_config_bundle_by_label_get(Ecore_Config_Server *srv,
+                                                             const char *label);
+   EAPI long                ecore_config_bundle_serial_get(Ecore_Config_Bundle *ns);
+   EAPI char               *ecore_config_bundle_label_get(Ecore_Config_Bundle *ns);
+
+   EAPI int                 ecore_config_init(const char *name);
+   EAPI int                 ecore_config_shutdown(void);
+
+   EAPI int                 ecore_config_system_init(void);
+   EAPI int                 ecore_config_system_shutdown(void);
+
+   EAPI int                 ecore_config_load(void);
+   EAPI int                 ecore_config_file_load(const char *file);
+   EAPI int                 ecore_config_save(void);
+   EAPI int                 ecore_config_file_save(const char *file);
+
+/* error codes */
+# define ECORE_CONFIG_ERR_NOTSUPP     (-16)
+# define ECORE_CONFIG_ERR_NOFILE      (-15)
+# define ECORE_CONFIG_ERR_META_DLFAIL (-14)
+# define ECORE_CONFIG_ERR_META_FILE   (-13)
+# define ECORE_CONFIG_ERR_META_FORMAT (-12)
+# define ECORE_CONFIG_ERR_MONMIS      (-11)
+# define ECORE_CONFIG_ERR_NOEXEC      (-10)
+# define ECORE_CONFIG_ERR_PARTIAL      (-9)
+# define ECORE_CONFIG_ERR_PATHEX       (-8)
+# define ECORE_CONFIG_ERR_TYPEMISMATCH (-7)
+# define ECORE_CONFIG_ERR_MUTEX        (-6)
+# define ECORE_CONFIG_ERR_NOTFOUND     (-5)    /* Error indicating that the item searched for could not be found. */
+# define ECORE_CONFIG_ERR_OOM          (-4)    /* Error given when the program runs out of memory. */
+# define ECORE_CONFIG_ERR_IGNORED      (-3)    /* Error occurred, but was ignored. */
+# define ECORE_CONFIG_ERR_NODATA       (-2)    /* Error given when necessary data is not provided. */
+# define ECORE_CONFIG_ERR_FAIL         (-1)    /* Failure result. */
+# define ECORE_CONFIG_ERR_SUCC          (0)    /* Success result. */
+
+# define ECORE_CONFIG_PARSE_HELP       (-2)    /* Help was displayed */
+# define ECORE_CONFIG_PARSE_EXIT       (-1)    /* An error occurred */
+# define ECORE_CONFIG_PARSE_CONTINUE    (0)    /* Arguments parsed successfully */
+
+/* convenience mathods in convenience.c */
+   /* FIXME: this should only be included if evas is present */
+   EAPI int                 ecore_config_evas_font_path_apply(Evas *evas);
+   EAPI char               *ecore_config_theme_search_path_get(void);
+   EAPI int                 ecore_config_theme_search_path_append(const char *append);
+     
+   EAPI char               *ecore_config_theme_default_path_get(void);
+   EAPI char               *ecore_config_theme_with_path_from_name_get(char *name);
+   EAPI char               *ecore_config_theme_with_path_get(const char *key);
+   EAPI void                ecore_config_args_display(void);
+   EAPI int                 ecore_config_args_parse(void);
+   EAPI void                ecore_config_args_callback_str_add(char short_opt,
+                                                              char *long_opt, char *desc,
+                                                              void (*func)(char *val, void *data),
+                                                              void *data);
+   EAPI void                ecore_config_args_callback_noarg_add(char short_opt,
+                                                                char *long_opt, char *desc,
+                                                                void (*func)(char *val, void *data),
+                                                                void *data);
+   EAPI void                ecore_config_app_describe(char *description);
+
+   EAPI int                 ecore_config_create(const char *key, void *val,
+                                               char short_opt, char *long_opt,
+                                               char *desc);
+   EAPI int                 ecore_config_typed_create(const char *key, void *val,
+                                                     int type, char short_opt,
+                                                     char *long_opt, char *desc);
+   EAPI int                 ecore_config_boolean_create(const char *key, int val,
+                                                       char short_opt, char *long_opt,
+                                                       char *desc);
+   EAPI int                 ecore_config_int_create(const char *key, int val,
+                                                   char short_opt, char *long_opt,
+                                                   char *desc);
+   EAPI int                 ecore_config_int_create_bound(const char *key, int val,
+                                                         int low, int high,
+                                                         int step, char short_opt,
+                                                         char *long_opt,
+                                                         char *desc);
+   EAPI int                 ecore_config_string_create(const char *key, char *val,
+                                                      char short_opt,
+                                                      char *long_opt, char *desc);
+   EAPI int                 ecore_config_float_create(const char *key, float val,
+                                                     char short_opt, char *long_opt,
+                                                     char *desc);
+   EAPI int                 ecore_config_float_create_bound(const char *key,
+                                                           float val, float low,
+                                                           float high, float step,
+                                                           char short_opt,
+                                                           char *long_opt,
+                                                           char *desc);
+   EAPI int                 ecore_config_argb_create(const char *key, char *val,
+                                                    char short_opt, char *long_opt,
+                                                    char *desc);
+   EAPI int                 ecore_config_theme_create(const char *key, char *val,
+                                                     char short_opt, char *long_opt,
+                                                     char *desc);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
diff --git a/src/lib/ecore_config/Makefile.am b/src/lib/ecore_config/Makefile.am
new file mode 100644 (file)
index 0000000..9ac305f
--- /dev/null
@@ -0,0 +1,65 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_ipc \
+-I$(top_srcdir)/ \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_ipc \
+-I$(top_builddir)/ \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+@EVAS_CFLAGS@ \
+@EET_CFLAGS@ \
+@EINA_CFLAGS@
+
+CLEANFILES = $(DB)
+
+if BUILD_ECORE_CONFIG
+
+#DB = system.db
+#$(DB): Makefile
+#      edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /e/theme/name str "winter"
+#      edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /e/font/path str "$(pkgdatadir)/data/fonts"
+#      edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /apps/web/browser str `which firefox 2>/dev/null || which phoenix 2>/dev/null || which mozilla 2>/dev/null || which opera 2>/dev/null || which konqueror 2>/dev/null || which epiphany 2>/dev/null`
+#      edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /apps/web/email str `which thunderbird 2>/dev/null || which mozilla 2>/dev/null || which kmail 2>/dev/null || which sylpheed 2>/dev/null || which evolution 2>/dev/null`
+
+lib_LTLIBRARIES = libecore_config.la
+
+include_HEADERS = Ecore_Config.h
+
+libecore_config_la_LDFLAGS = -no-undefined -version-info @version_info@ @ecore_config_release_info@
+
+#config_DATA = $(DB)
+#configdir = $(pkgdatadir)
+
+libecore_config_la_SOURCES = \
+ecore_config.c \
+ecore_config_util.c \
+ecore_config_storage.c \
+ecore_config_extra.c \
+ecore_config_db.c
+
+libecore_config_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EET_LIBS@ \
+@EINA_LIBS@ \
+@EVAS_LIBS@
+
+if BUILD_ECORE_IPC
+
+libecore_config_la_SOURCES += \
+ecore_config_ipc_main.c \
+ecore_config_ipc_ecore.c
+
+libecore_config_la_LIBADD += $(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la
+
+endif
+
+endif
+
+EXTRA_DIST = \
+ecore_config_ipc.h \
+ecore_config_private.h \
+ecore_config_util.h
diff --git a/src/lib/ecore_config/ecore_config.c b/src/lib/ecore_config/ecore_config.c
new file mode 100644 (file)
index 0000000..88ed306
--- /dev/null
@@ -0,0 +1,1873 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "Ecore_Config.h"
+#include "ecore_config_private.h"
+#include "ecore_config_ipc.h"
+
+#include "ecore_config_util.h"
+int  _ecore_config_log_dom = -1;
+int                  DEBUG = 0;
+EAPI Ecore_Config_Server *__ecore_config_server_global = NULL;
+EAPI Ecore_Config_Server *__ecore_config_server_local = NULL;
+EAPI Ecore_Config_Bundle *__ecore_config_bundle_local = NULL;
+EAPI char                *__ecore_config_app_name = NULL;
+int                  __ecore_config_system_init = 0;
+
+static int           _ecore_config_system_init_no_load(void);
+static int           _ecore_config_system_load(void);
+
+static inline void  *__ecore_argb_to_long(int a, int r, int g, int b, long *v);
+static inline void  *__ecore_argbstr_to_long(const char *argb, long *v);
+
+static const char  *_ecore_config_type[] =
+   { "undefined", "integer", "float", "string", "colour", "theme", "boolean", "structure" };
+
+/**
+ * @defgroup Ecore_Config_Property_Group Ecore Config Property Functions
+ *
+ * Functions that retrieve or set the attributes relating to a property.
+ */
+
+/**
+ * Removes the given property from the local configuration and destroys it.
+ * @param   e Property to destroy.
+ * @return  @c NULL
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI Ecore_Config_Prop  *
+ecore_config_dst(Ecore_Config_Prop * e)
+{
+   Ecore_Config_Bundle *t;
+   Ecore_Config_Prop  *p, *c;
+   Ecore_Config_Listener_List *l;
+
+   p = NULL;
+   t = __ecore_config_bundle_local;
+   c = t->data;
+
+   if (!e || !e->key)
+      return NULL;
+   if (t)
+     {
+       if (t->data == e)
+          t->data = e->next;
+       else
+         {
+            do
+              {
+                 p = c;
+                 c = c->next;
+              }
+            while (c && (c != e));
+            if (c)             /* remove from list if even in there */
+               p->next = c->next;
+         }
+     }
+
+   while (e->listeners)
+     {
+       l = e->listeners;
+       e->listeners = e->listeners->next;
+       free(l);
+     }
+
+   if (e->key)
+      free(e->key);
+   if (e->ptr && ((e->type == ECORE_CONFIG_STR) || (e->type == ECORE_CONFIG_THM)))
+      free(e->ptr);
+
+   memset(e, 0, sizeof(Ecore_Config_Prop));
+   free(e);
+
+   return NULL;
+}
+
+/**
+ * @defgroup Ecore_Config_Get_Group Configuration Retrieve Functions
+ *
+ * Functions that retrieve configuration values, based on type.
+ */
+
+/**
+ * Returns the property with the given key.
+ * @param   key The unique name of the wanted property.
+ * @return  The property that corresponds to the given key.  @c NULL if the
+ *          key could not be found.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI Ecore_Config_Prop  *
+ecore_config_get(const char *key)
+{
+   Ecore_Config_Bundle *t;
+   Ecore_Config_Prop  *e;
+
+   t = __ecore_config_bundle_local;
+   if (!t || !key)
+      return NULL;
+   e = t->data;
+   while (e)
+     {
+       if (!strcmp(key, e->key))
+          return e;
+       e = e->next;
+     }
+   return NULL;
+}
+
+/**
+ * Returns the type of the property.
+ * @param   e Property to get the type of.
+ * @returns The type of the property.  If the property is invalid, then the
+ *          string "not found" is returned.
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI const char         *
+ecore_config_type_get(const Ecore_Config_Prop * e)
+{
+   if (e)
+     {
+       return _ecore_config_type[e->type];
+     }
+   return "not found";
+}
+
+/**
+ * Returns the specified property as a string.
+ * @param   key The property key.
+ * @return  The string value of the property.  The function returns @c NULL if
+ *          the property is not a string or is not set.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI char               *
+ecore_config_string_get(const char *key)
+{
+   return _ecore_config_string_get( ecore_config_get(key) );
+}
+
+char               *
+_ecore_config_string_get(Ecore_Config_Prop *e)
+{
+   return (e && (e->type == ECORE_CONFIG_STR) && e->ptr) ? strdup(e->ptr) : NULL;
+}
+
+/**
+ * Returns the specified property as an integer.
+ * @param   key The property key.
+ * @return  The value of the property.  The function returns -1 if the
+ *          property is not an integer or is not set.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI int
+ecore_config_boolean_get(const char *key)
+{
+   return _ecore_config_boolean_get( ecore_config_get(key) );
+}
+
+int
+_ecore_config_boolean_get(Ecore_Config_Prop *e)
+{
+   return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_BLN))) ? (e->val != 0) : -1;
+}
+
+/**
+ * Returns the specified property as a long integer.
+ * @param   key The property key.
+ * @return  The integer value of the property.  The function returns 0 if the
+ *          property is not an integer or is not set.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI long
+ecore_config_int_get(const char *key)
+{
+   return _ecore_config_int_get( ecore_config_get(key) );
+}
+
+long
+_ecore_config_int_get(Ecore_Config_Prop *e)
+{
+   return (e && ((e->type == ECORE_CONFIG_INT) || (e->type == ECORE_CONFIG_RGB))) ? e->val : 0L;
+}
+
+/**
+ * Returns the specified property as a float.
+ * @param   key The property key.
+ * @return  The float value of the property.  The function returns 0.0 if the 
+ *          property is not a float or is not set.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI float
+ecore_config_float_get(const char *key)
+{
+   return _ecore_config_float_get( ecore_config_get(key) );
+}
+
+float
+_ecore_config_float_get(Ecore_Config_Prop *e)
+{
+   return (e && (e->type == ECORE_CONFIG_FLT)) ? ((float)e->val / ECORE_CONFIG_FLOAT_PRECISION) : 0.0;
+}
+
+/**
+ * Finds the alpha, red, green and blue values of a color property.
+ * @param   key The property key.
+ * @param   a   A pointer to an integer to store the alpha value into.
+ * @param   r   A pointer to an integer to store the red value into.
+ * @param   g   A pointer to an integer to store the green value into.
+ * @param   b   A pointer to an integer to store the blue value into.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_FAIL
+ *          otherwise.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI int
+ecore_config_argb_get(const char *key, int *a, int *r, int *g, int *b)
+{
+   return _ecore_config_argb_get( ecore_config_get(key), a, r, g, b);
+}
+
+int
+_ecore_config_argb_get(Ecore_Config_Prop *e, int *a, int *r, int *g, int *b)
+{
+   if (e && ((e->type == ECORE_CONFIG_RGB)))
+     {
+       if(a) *a = (e->val >> 24) & 0xff;
+       if(r) *r = (e->val >> 16) & 0xff;
+       if(g) *g = (e->val >>  8) & 0xff;
+       if(b) *b =  e->val        & 0xff;
+       return ECORE_CONFIG_ERR_SUCC;
+     }
+   return ECORE_CONFIG_ERR_FAIL;
+}
+
+/**
+ * Returns a color property as a long
+ * @param   key The property key.
+ * @return  ARGB data as long
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI long
+ecore_config_argbint_get(const char *key)
+{
+   return _ecore_config_argbint_get( ecore_config_get(key) );
+}
+
+long
+_ecore_config_argbint_get(Ecore_Config_Prop *e)
+{
+   if (e && ((e->type == ECORE_CONFIG_RGB)))
+     {
+       return e->val;
+     }
+   return 0L;
+}
+
+/**
+ * Returns a color property as a string of hexadecimal characters.
+ * @param   key The property key.
+ * @return  A string of hexadecimal characters in the format #aarrggbb.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI char               *
+ecore_config_argbstr_get(const char *key)
+{
+   return _ecore_config_argbstr_get( ecore_config_get(key) );
+}
+
+char               *
+_ecore_config_argbstr_get(Ecore_Config_Prop *e)
+{
+   char               *r;
+
+   r = NULL;
+   esprintf(&r, "#%08x", _ecore_config_int_get(e));
+   return r;
+}
+
+/**
+ * Returns a theme property.
+ * @param   key The property key.
+ * @return  The name of the theme the property refers to.  The function returns
+ *          @c NULL if the property is not a theme or is not set.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI char               *
+ecore_config_theme_get(const char *key)
+{
+   return _ecore_config_theme_get( ecore_config_get(key) );
+}
+
+char               *
+_ecore_config_theme_get(Ecore_Config_Prop *e)
+{
+   return (e && (e->type == ECORE_CONFIG_THM)) ? strdup(e->ptr) : NULL;
+}
+
+/**
+ * Retrieves the key as a string.
+ * @param   key The property key.
+ * @return  Returns a character array in the form of 'key:type=value'.  @c NULL
+ *          is returned if the property does not exist.
+ * @ingroup Ecore_Config_Get_Group
+ */
+EAPI char               *
+ecore_config_as_string_get(const char *key)
+{
+   Ecore_Config_Prop  *e;
+   char               *val;
+   char               *r;
+
+   val = NULL;
+   r = NULL;
+   if (!(e = ecore_config_get(key)))
+      ERR("no such property, \"%s\"...", key);
+   else
+     {
+       switch (e->type)
+          {
+            case ECORE_CONFIG_NIL:
+               val = strdup("<nil>");
+               break;
+            case ECORE_CONFIG_INT:
+               esprintf(&val, "%ld",    _ecore_config_int_get(e));
+               break;
+            case ECORE_CONFIG_BLN:
+               esprintf(&val, "%ld",    _ecore_config_boolean_get(e));
+               break;
+            case ECORE_CONFIG_FLT:
+               esprintf(&val, "%lf",    _ecore_config_float_get(e));
+               break;
+            case ECORE_CONFIG_STR:
+               esprintf(&val, "\"%s\"", _ecore_config_string_get(e));
+               break;
+            case ECORE_CONFIG_RGB:
+               esprintf(&val, "#%08x",  _ecore_config_int_get(e));
+               break;
+            case ECORE_CONFIG_THM:
+               esprintf(&val, "\"%s\"", _ecore_config_theme_get(e));
+               break;
+            case ECORE_CONFIG_SCT:
+               break;
+            default:
+               esprintf(&r, "%s:unknown_type", key);
+               break;
+          }
+       if (val)
+          {
+            esprintf(&r, "%s:%s=%s", key, _ecore_config_type[e->type], val);
+            free(val);
+          }
+     }
+   return r;
+}
+
+EAPI int
+ecore_config_bound(Ecore_Config_Prop * e)
+{
+   int                 ret;
+   long                v;
+
+   ret = ECORE_CONFIG_ERR_SUCC;
+
+   if (!e)
+      return ECORE_CONFIG_ERR_FAIL;
+   if (e->flags & ECORE_CONFIG_FLAG_BOUNDS)
+     {
+       if ((e->val < e->lo))
+         {
+           WRN("ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...",
+              e->key, e->val, e->lo);
+            e->val = e->lo;
+         }
+       else if ((e->val > e->hi))
+         {
+           WRN("ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...",
+              e->key, e->val, e->hi);
+            e->val = e->hi;
+         }
+       else
+          ret = ECORE_CONFIG_ERR_IGNORED;
+     }
+   else
+      ret = ECORE_CONFIG_ERR_IGNORED;
+
+   if (e->step)
+     {
+       v = ((int)(e->val / e->step)) * e->step;
+       if (v != e->val)
+         {
+            if (e->type == ECORE_CONFIG_FLT)
+              WRN("ecore_config_bound(\"%s\"): float value %f not a multiple of %f, adjusted to %f...",
+                 e->key, ((double)e->val) / ECORE_CONFIG_FLOAT_PRECISION,
+                 ((double)e->step) / ECORE_CONFIG_FLOAT_PRECISION,
+                 ((double)v) / ECORE_CONFIG_FLOAT_PRECISION);
+            else
+              WRN("ecore_config_bound(\"%s\"): integer value %ld not a multiple of %ld, adjusted to %ld...",
+                 e->key, e->val, e->step, v);
+            ret = ECORE_CONFIG_ERR_SUCC;
+            e->val = v;
+         }
+     }
+
+   return ret;
+}
+
+/**
+ * Tries to guess the type of a property.
+ *
+ * This function first checks to see if the property exists.  If it does, then
+ * the type of the stored property is returned.  Otherwise, the function tries
+ * to guess the type of the property based on @p val.
+ *
+ * @param  key The property key.
+ * @param  val The value in string form.
+ * @return The type of the property determined by the function.  Note that if
+ *         val is @c NULL, @c ECORE_CONFIG_NIL will be returned.
+ */
+EAPI int
+ecore_config_type_guess(const char *key, const char *val)
+{
+   Ecore_Config_Prop  *p;
+   char               *l;
+
+   l = NULL;
+
+   if (key && (p = ecore_config_get(key)) && p->type != ECORE_CONFIG_NIL)
+      return p->type;
+
+   if (!val)
+      return ECORE_CONFIG_NIL;
+   if (val[0] == '#')
+      return ECORE_CONFIG_RGB;
+   strtol(val, &l, 10);
+   if (*l)
+     {
+       float               f;
+
+       if (sscanf(val, "%f%*s", &f) != 1)
+          return ECORE_CONFIG_STR;
+       return ECORE_CONFIG_FLT;
+     }
+   return ECORE_CONFIG_INT;
+}
+
+static int
+ecore_config_typed_val(Ecore_Config_Prop * e, const void *val, int type)
+{
+
+   if (!e)
+     return ECORE_CONFIG_ERR_NODATA;
+
+   if (!(val) && (type != ECORE_CONFIG_NIL && type != ECORE_CONFIG_SCT))
+      e->ptr = NULL;
+   else
+     {
+       if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN)
+         {
+            e->val = (long) *((int *)val);
+            e->type = type;
+         }
+       else if (type == ECORE_CONFIG_STR || type == ECORE_CONFIG_THM)
+         {
+            if (!(e->ptr = strdup(val)))
+               return ECORE_CONFIG_ERR_OOM;
+            if (e->type == ECORE_CONFIG_NIL)
+               e->type = type;
+         }
+       else if (type == ECORE_CONFIG_RGB)
+         {
+            __ecore_argbstr_to_long((char *)val, &e->val);
+            e->type = ECORE_CONFIG_RGB;
+         }
+       else if (type == ECORE_CONFIG_FLT)
+         {
+            e->val = (long) ((*((float *)val)) * ECORE_CONFIG_FLOAT_PRECISION);
+            e->type = ECORE_CONFIG_FLT;
+         }
+       else if (type == ECORE_CONFIG_SCT)
+         {
+            e->type = ECORE_CONFIG_SCT;
+         }
+       else
+         {
+          e->type = ECORE_CONFIG_NIL;
+         }
+
+       ecore_config_bound(e);
+       e->flags |= ECORE_CONFIG_FLAG_MODIFIED;
+       e->flags &= ~ECORE_CONFIG_FLAG_CMDLN;
+       return ECORE_CONFIG_ERR_SUCC;
+     }
+   return ECORE_CONFIG_ERR_IGNORED;
+}
+
+static int
+ecore_config_typed_add(const char *key, const void *val, int type)
+{
+   int error = ECORE_CONFIG_ERR_SUCC;
+   Ecore_Config_Prop  *e = NULL;
+   Ecore_Config_Bundle *t;
+
+   t = __ecore_config_bundle_local;
+   if (!key)
+      return ECORE_CONFIG_ERR_NODATA;
+
+   if (!(e = calloc(1, sizeof(Ecore_Config_Prop))))
+     {
+       return ECORE_CONFIG_ERR_OOM;
+     }
+   else if (!(e->key = strdup(key)))
+     {
+       error = ECORE_CONFIG_ERR_OOM;
+     }
+   else if ((error = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC)
+     {
+       if (t)
+          {
+            e->next = t->data;
+            t->data = e;
+          }
+       return ECORE_CONFIG_ERR_SUCC;
+     }
+
+   if(e->key)
+     free(e->key);
+   if(e)
+     free(e);
+
+   if (error == ECORE_CONFIG_ERR_SUCC)
+      error = ECORE_CONFIG_ERR_FAIL;
+
+   return error;
+}
+
+static int
+ecore_config_add(const char *key, const char *val)
+{
+   int                 type;
+
+   type = ecore_config_type_guess(key, val);
+   return ecore_config_typed_add(key, val, type);
+}
+
+/**
+ * Sets the description field of the indicated property.
+ * @param   key  The property key.
+ * @param   desc Description string.
+ * @note    The description string is copied for the property's use.  You can
+ *          free @p desc once this function is called.
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI int
+ecore_config_describe(const char *key, const char *desc)
+{
+   Ecore_Config_Prop  *e;
+
+   if (!(e = ecore_config_get(key)))
+      return ECORE_CONFIG_ERR_NODATA;
+   e->description = strdup(desc);
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/**
+ * Set the short option character of a property.
+ * @param   key       The property key.
+ * @param   short_opt Character used to indicate the value of a property
+ *                    given on the command line.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
+ *          is returned if the property does not exist.
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI int
+ecore_config_short_opt_set(const char *key, char short_opt)
+{
+   Ecore_Config_Prop  *e;
+
+   if (!(e = ecore_config_get(key)))
+      return ECORE_CONFIG_ERR_NODATA;
+   e->short_opt = short_opt;
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/**
+ * Set the long option string of the property.
+ * @param   key      The property key.
+ * @param   long_opt String used to indicate the value of a property given
+ *                   on the command line.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
+ *          is returned if the property does not exist.
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI int
+ecore_config_long_opt_set(const char *key, const char *long_opt)
+{
+   Ecore_Config_Prop  *e;
+
+   if (!(e = ecore_config_get(key)))
+      return ECORE_CONFIG_ERR_NODATA;
+   if (e->long_opt)
+      free(e->long_opt);
+   if (long_opt)
+      e->long_opt = strdup(long_opt);
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+static void
+_ecore_config_listener_fire(Ecore_Config_Prop *prop)
+{
+   Ecore_Config_Listener_List *l;
+   for (l = prop->listeners; l; l = l->next)
+     l->listener(prop->key, prop->type, l->tag, l->data);
+
+   /* fire change listeners for the generic struct container etc */
+   if (prop->parent)
+     _ecore_config_listener_fire(prop->parent);
+}
+
+/**
+ * Sets the indicated property to the given value and type.
+ * @param   key  The property key.
+ * @param   val  A pointer to the value to set the property to.
+ * @param   type The type of the property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Property_Group
+ */
+EAPI int
+ecore_config_typed_set(const char *key, const void *val, int type)
+{
+   Ecore_Config_Prop  *e;
+   int                 ret;
+
+   if (!key)
+      return ECORE_CONFIG_ERR_NODATA;
+/*  if (!t) { * global prop *
+    e=ecore_config_get(key);
+    if (e)
+      for(l=e->listeners;l;l=l->next)
+        l->listener(e->key,e->type,l->tag,l->data,t);
+    return ECORE_CONFIG_ERR_SUCC;
+  }
+*/
+   if (!(e = ecore_config_get(key)))
+      return ecore_config_typed_add(key, val, type);
+
+   if ((ret = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC)
+     {
+       _ecore_config_listener_fire(e);
+     }
+   else
+     {
+       ERR("ecore_config_typed_set(\"%s\"): ecore_config_typed_val() failed: %d",
+           key, ret);
+     }
+
+   return ret;
+}
+
+/**
+ * @defgroup Ecore_Config_Set_Group Ecore Config Setters
+ *
+ * Functions that set the value of a property.
+ */
+
+/**
+ * Sets the indicated property to the value indicated by @a val.
+ * @param   key The property key.
+ * @param   val String representation of value to set.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_set(const char *key, const char *val)
+{
+   int                 type;
+   int                 tmpi;
+   float               tmpf;
+   long                tmpl;
+
+   type = ecore_config_type_guess(key, val);
+   if (type == ECORE_CONFIG_INT || type == ECORE_CONFIG_BLN)
+     {
+       tmpi = atoi(val);
+       return ecore_config_typed_set(key, &tmpi, type);
+     }
+   else if (type == ECORE_CONFIG_FLT)
+     {
+       tmpf = atof(val);
+       return ecore_config_typed_set(key, &tmpf, type);
+     }
+   else if (type == ECORE_CONFIG_RGB)
+     {
+       __ecore_argbstr_to_long(val, &tmpl);
+       return ecore_config_typed_set(key, &tmpl, type);
+     }
+   else
+      return ecore_config_typed_set(key, val, type);
+}
+
+/**
+ * Sets the indicated property to the value given in the string.
+ * @param   key The property key.
+ * @param   val String representation of the value.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_as_string_set(const char *key, const char *val)
+{
+   return ecore_config_set(key, val);
+}
+
+/**
+ * Sets the indicated property to the given boolean.
+ * @param   key The property key.
+ * @param   val Boolean integer to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_boolean_set(const char *key, int val)
+{
+   val = val ? 1 : 0;
+   return ecore_config_typed_set(key, &val, ECORE_CONFIG_BLN);
+}
+
+/**
+ * Sets the indicated property to the given integer.
+ * @param   key The property key.
+ * @param   val Integer to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_int_set(const char *key, int val)
+{
+   return ecore_config_typed_set(key, &val, ECORE_CONFIG_INT);
+}
+
+/**
+ * Sets the indicated property to the given string.
+ * @param   key The property key.
+ * @param   val String to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_string_set(const char *key, const char *val)
+{
+   return ecore_config_typed_set(key, val, ECORE_CONFIG_STR);
+}
+
+/**
+ * Sets the indicated property to the given float value.
+ * @param   key The property key.
+ * @param   val Float to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_float_set(const char *key, float val)
+{
+   return ecore_config_typed_set(key, &val, ECORE_CONFIG_FLT);
+}
+
+/**
+ * Sets the indicated property to a color value.
+ * @param   key The property key
+ * @param   a integer 0..255
+ * @param   r integer 0..255
+ * @param   g integer 0..255
+ * @param   b integer 0..255
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_argb_set(const char *key, int a, int r, int g, int b)
+{
+   long v = 0;
+   return ecore_config_typed_set(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a color value.
+ * @param   key The property key
+ * @param   argb ARGB data as long
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_argbint_set(const char *key, long argb)
+{
+   return ecore_config_typed_set(key, &argb, ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a color value.
+ * @param   key The property key
+ * @param   val Color value in ARGB format.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_argbstr_set(const char *key, const char *val)
+{
+   long v = 0;
+   return ecore_config_typed_set(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a theme name.
+ * @param   key The property key.
+ * @param   val String giving the name of the theme.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_theme_set(const char *key, const char *val)
+{
+   return ecore_config_typed_set(key, val, ECORE_CONFIG_THM);
+}
+
+/**
+ * Sets the theme preview group of an indicated property.
+ * @param   key   The property key.
+ * @param   group The group name.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Set_Group
+ */
+EAPI int
+ecore_config_theme_preview_group_set(const char *key, const char *group)
+{
+   int                 ret;
+   Ecore_Config_Prop  *e;
+
+   ret = ECORE_CONFIG_ERR_SUCC;
+   if (!(e = ecore_config_get(key)))
+     {                         /* prop doesn't exist yet */
+       if ((ret = ecore_config_typed_add(key, "", ECORE_CONFIG_THM)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */
+          return ret;          /* ...failed */
+       if (!(e = ecore_config_get(key)))       /* get handle */
+          return ECORE_CONFIG_ERR_FAIL;
+     }
+   if (e->data)
+      free(e->data);
+   e->data = strdup(group);
+
+   return ret;
+}
+
+EAPI int
+ecore_config_typed_default(const char *key, const void *val, int type)
+{
+   int                 ret;
+   Ecore_Config_Prop  *e;
+
+   ret = ECORE_CONFIG_ERR_SUCC;
+
+   if (!(e = ecore_config_get(key)))
+     {                         /* prop doesn't exist yet */
+       if ((ret = ecore_config_typed_add(key, val, type)) != ECORE_CONFIG_ERR_SUCC)    /* try to add it */
+          return ret;          /* ...failed */
+       if (!(e = ecore_config_get(key)))       /* get handle */
+          return ECORE_CONFIG_ERR_FAIL;
+       e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED;
+     }
+   else if (!(e->flags & ECORE_CONFIG_FLAG_MODIFIED) && !(e->flags & ECORE_CONFIG_FLAG_SYSTEM))
+     {
+       ecore_config_typed_set(key, val, type);
+       if (!(e = ecore_config_get(key)))       /* get handle */
+          return ECORE_CONFIG_ERR_FAIL;
+       e->flags = e->flags & ~ECORE_CONFIG_FLAG_MODIFIED;
+     }
+   return ret;
+}
+
+/**
+ * @defgroup Ecore_Config_Default_Group Ecore Config Defaults
+ *
+ * Functions that are used to set the default values of properties.
+ */
+
+/**
+ * Sets the indicated property if it has not already been set or loaded.
+ * @param   key  The property key.
+ * @param   val  Default value of the key.
+ * @param   lo   Lowest valid value for the key.
+ * @param   hi   Highest valid value for the key.
+ * @param   step Used by integer and float values.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there are no errors.
+ * @note    The @p lo, @p hi and @p step parameters are only used when storing
+ *          integer and float properties.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_default(const char *key, const char *val, float lo, float hi, float step)
+{
+   int                 ret, type;
+   Ecore_Config_Prop  *e;
+
+   type = ecore_config_type_guess(key, val);
+   ret = ecore_config_typed_default(key, val, type);
+   e = ecore_config_get(key);
+   if (e)
+     {
+       if (type == ECORE_CONFIG_INT)
+         {
+            e->step = step;
+            e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+            e->lo = lo;
+            e->hi = hi;
+            ecore_config_bound(e);
+         }
+       else if (type == ECORE_CONFIG_FLT)
+         {
+            e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
+            e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+            e->lo = (int)(lo * ECORE_CONFIG_FLOAT_PRECISION);
+            e->hi = (int)(hi * ECORE_CONFIG_FLOAT_PRECISION);
+            ecore_config_bound(e);
+         }
+     }
+
+   return ret;
+}
+
+/**
+ * Sets the indicated property to the given boolean if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @param   val Boolean Integer to set the value to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there are no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_boolean_default(const char *key, int val)
+{
+   val = val ? 1 : 0;
+   return ecore_config_typed_default(key, &val, ECORE_CONFIG_BLN);
+}
+
+/**
+ * Sets the indicated property to the given integer if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @param   val Integer to set the value to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there are no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_int_default(const char *key, int val)
+{
+   return ecore_config_typed_default(key, &val, ECORE_CONFIG_INT);
+}
+
+/**
+ * Sets the indicated property to the given integer if the property has not yet
+ * been set.
+ *
+ * The bounds and step values are set regardless.
+ *
+ * @param   key  The property key.
+ * @param   val  Integer to set the property to.
+ * @param   low  Lowest valid integer value for the property.
+ * @param   high Highest valid integer value for the property.
+ * @param   step Increment value for the property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_int_default_bound(const char *key, int val, int low, int high,
+                              int step)
+{
+   Ecore_Config_Prop  *e;
+   int                 ret;
+
+   ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_INT);
+   e = ecore_config_get(key);
+   if (e)
+     {
+       e->step = step;
+       e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+       e->lo = low;
+       e->hi = high;
+       ecore_config_bound(e);
+     }
+
+   return ret;
+}
+
+/**
+ * Sets the indicated property to the given string if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @param   val String to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_string_default(const char *key, const char *val)
+{
+   return ecore_config_typed_default(key, val, ECORE_CONFIG_STR);
+}
+
+/**
+ * Sets the indicated property to the given float if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @param   val Float to set the property to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_float_default(const char *key, float val)
+{
+   return ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT);
+}
+
+/**
+ * Sets the indicated property to the given float if the property has not yet
+ * been set.
+ *
+ * The bounds and step values are set regardless.
+ *
+ * @param   key  The property key.
+ * @param   val  Float to set the property to.
+ * @param   low  Lowest valid integer value for the property.
+ * @param   high Highest valid float value for the property.
+ * @param   step Increment value for the property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if there were no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_float_default_bound(const char *key, float val, float low,
+                                float high, float step)
+{
+   Ecore_Config_Prop  *e;
+   int                 ret;
+
+   ret = ecore_config_typed_default(key, &val, ECORE_CONFIG_FLT);
+   e = ecore_config_get(key);
+   if (e)
+     {
+       e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
+       e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+       e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION);
+       e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION);
+       ecore_config_bound(e);
+     }
+
+   return ret;
+}
+
+/**
+ * Sets the indicated property to a color value if the property has not yet
+ * been set.
+ * @param  key The property key.
+ * @param  a integer 0..255
+ * @param  r integer 0..255
+ * @param  g integer 0..255
+ * @param  b integer 0..255
+ * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_argb_default(const char *key, int a, int r, int g, int b)
+{
+   long v = 0;
+   return ecore_config_typed_default(key, __ecore_argb_to_long(a,r,g,b, &v), ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a color value if the property has not yet
+ * been set.
+ * @param  key The property key.
+ * @param  argb ARGB data as long
+ * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_argbint_default(const char *key, long argb)
+{
+   return ecore_config_typed_default(key, &argb, ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a color value if the property has not yet
+ * been set.
+ * @param  key The property key.
+ * @param  val Color value in ARGB format.
+ * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_argbstr_default(const char *key, const char *val)
+{
+   long v = 0;
+   return ecore_config_typed_default(key, __ecore_argbstr_to_long(val, &v), ECORE_CONFIG_RGB);
+}
+
+/**
+ * Sets the indicated property to a theme name if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @param   val String giving the name of the theme.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Default_Group
+ */
+EAPI int
+ecore_config_theme_default(const char *key, const char *val)
+{
+   return ecore_config_typed_default(key, val, ECORE_CONFIG_THM);
+}
+
+/**
+ * @defgroup Ecore_Config_Struct_Group Ecore Config Structures
+ *
+ * Functions that are used to create structures of properties.
+ */
+
+/**
+ * Sets the indicated property to a structure if the property has not yet
+ * been set.
+ * @param   key The property key.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_create(const char *key)
+{
+   WRN("you are using ecore_config structures. These are very young");
+   WRN(" and not complete - you have been warned");
+
+   return ecore_config_typed_default(key, NULL, ECORE_CONFIG_SCT);
+}
+
+static int
+_ecore_config_struct_append(Ecore_Config_Prop *sct, Ecore_Config_Prop *add)
+{
+   Eina_List *l;
+
+   if (!sct || !add || sct->type != ECORE_CONFIG_SCT)
+     return ECORE_CONFIG_ERR_IGNORED;
+
+   l = sct->data;
+   sct->data = eina_list_append(l, add);
+   add->parent = sct;
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+static int
+_ecore_config_struct_typed_add(const char *key, const char *name, const void *val,
+    int type)
+{
+   char *subkey;
+   int ret;
+
+   subkey = malloc((strlen(key) + strlen(name) + 2) * sizeof(char));
+   strcpy(subkey, key);
+   strcat(subkey, ".");
+   strcat(subkey, name);
+
+   ecore_config_typed_default(subkey, val, type);
+   ret = _ecore_config_struct_append(ecore_config_get(key),
+                                     ecore_config_get(subkey));
+   free(subkey);
+   return ret;   
+}
+
+/**
+ * Add an int property to the named structure. The property is set if it has not
+ * yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   val the int to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_int_add(const char *key, const char *name, int val)
+{
+   return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_INT);
+}
+
+/**
+ * Add a float property to the named structure. The property is set if it has
+ * not yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   val The float to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_float_add(const char *key, const char *name, float val)
+{
+   return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_FLT);
+}
+
+/**
+ * Add a string property to the named structure. The property is set if it has
+ * not yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   val The string to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_string_add(const char *key, const char *name, const char* val)
+{
+   return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_STR);
+}
+
+/**
+ * Add an argb property to the named structure. The property is set if it has
+ * not yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   a The alpha to default to
+ * @param   r The red to default to
+ * @param   g The green to default to
+ * @param   b The blue to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_argb_add(const char *key, const char *name, int a, int r,
+                             int g, int b)
+{
+   long argb;
+  
+   __ecore_argb_to_long(a, r, g, b, &argb);
+   return _ecore_config_struct_typed_add(key, name, &argb, ECORE_CONFIG_RGB);
+}
+
+/**
+ * Add a theme property to the named structure. The property is set if it has
+ * not yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   val The theme name to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_theme_add(const char *key, const char *name, const char* val)
+{
+   return _ecore_config_struct_typed_add(key, name, val, ECORE_CONFIG_THM);
+}
+
+/**
+ * Add a boolean property to the named structure. The property is set if it has
+ * not yet been set.
+ * @param   key The key of the structure to add to.
+ * @param   name The name of the item to add - this will be appended to the key
+ * @param   val The boolean to default to
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the property is set successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_boolean_add(const char *key, const char *name, int val)
+{
+   val = val ? 1 : 0;
+   return _ecore_config_struct_typed_add(key, name, &val, ECORE_CONFIG_BLN);
+}
+
+/**
+ * Get the contents of a defined structure property and load it into the passed
+ * C struct
+ * @param   key The name of the structure property to look up.
+ * @param   data The struct to write into.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if the structure is written successfully.
+ * @ingroup Ecore_Config_Struct_Group
+ */
+EAPI int
+ecore_config_struct_get(const char *key, void *data)
+{
+   Ecore_Config_Prop *e, *f;
+   Eina_List *l;
+   unsigned char *ptr;
+   long argb;
+
+   e = ecore_config_get(key);
+   if (!e)
+     return ECORE_CONFIG_ERR_NODATA;
+
+   l = e->data;
+   ptr = data;
+   while (l)
+     {
+       f = (Ecore_Config_Prop *) l->data;
+       switch (f->type)
+         {
+            case ECORE_CONFIG_INT:
+              *((int *) ptr) = _ecore_config_int_get(f);
+              ptr += sizeof(int);
+            break;
+            case ECORE_CONFIG_BLN:
+              *((int *) ptr) = _ecore_config_boolean_get(f);
+              ptr += sizeof(int);
+            break;
+            case ECORE_CONFIG_FLT:
+              *((float *) ptr) = _ecore_config_float_get(f);
+              ptr += sizeof(float);
+            break;
+            case ECORE_CONFIG_STR:
+            case ECORE_CONFIG_THM:
+              *((char **) ptr) = _ecore_config_string_get(f);
+              ptr += sizeof(char *);
+            break;
+            case ECORE_CONFIG_RGB:
+              argb = _ecore_config_argbint_get(f);
+              *((int *) ptr) = (argb >> 24) & 0xff;
+              ptr += sizeof(int);
+              *((int *) ptr) = (argb >> 16) & 0xff;
+              ptr += sizeof(int);
+              *((int *) ptr) = (argb >> 8) & 0xff;
+              ptr += sizeof(int);
+              *((int *) ptr) = argb & 0xff;
+              ptr += sizeof(int);
+            break;
+            default:
+              WRN("ARGH - STRUCT coding not implemented yet");
+         }
+       l = eina_list_next(l);
+     }
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/**
+ * @defgroup Ecore_Config_Listeners_Group Ecore Config Listeners
+ *
+ * Functions that set and unset property listener callbacks.
+ */
+
+/**
+ * Adds a callback function to the list of functions called when a property
+ * changes.
+ * @param   name     Name of the callback.
+ * @param   key      The key of the property to listen to.
+ * @param   listener Listener callback function.
+ * @param   tag      Tag to pass to @p listener when it is called.
+ * @param   data     Data to pass to @p listener when it is called.
+ * @return  @c ECORE_CONFIG_ERR_SUCC if successful in setting up the callback.
+ * @ingroup Ecore_Config_Listeners_Group
+ */
+EAPI int
+ecore_config_listen(const char *name, const char *key,
+                   Ecore_Config_Listener listener, int tag, void *data)
+{
+   Ecore_Config_Prop  *e;
+   Ecore_Config_Listener_List *l;
+
+   if (!key)
+      return ECORE_CONFIG_ERR_NODATA;
+
+   if (!(e = ecore_config_get(key)))
+     {
+       int                 ret = ecore_config_add(key, "");
+
+       if (ret != ECORE_CONFIG_ERR_SUCC)
+         {
+            ERR("ecore_config_listen: ecore_config_add(\"%s\") failed: %d",
+                key, ret);
+            return ret;
+         }
+       if (!(e = ecore_config_get(key)))
+         {
+            ERR("ecore_config_listen: list of properties corrupted!?");
+            return ECORE_CONFIG_ERR_FAIL;
+         }
+     }
+
+   for (l = e->listeners; l; l = l->next)
+      if (!strcmp(l->name, name) || (l->listener == listener))
+       {
+          ERR("ecore_config_listen: %s is already listening for changes of %s...",
+            name, key);
+          return ECORE_CONFIG_ERR_IGNORED;
+       }
+
+   if (!(l = malloc(sizeof(Ecore_Config_Listener_List))))
+      return ECORE_CONFIG_ERR_OOM;
+
+   ERR("registering listener \"%s\" for \"%s\" (%d)...", name, key, e->type);
+
+   memset(l, 0, sizeof(Ecore_Config_Listener_List));
+
+   l->listener = listener;
+   l->name = name;
+   l->data = data;
+   l->tag = tag;
+   l->next = e->listeners;
+   e->listeners = l;
+
+   if (e->type != ECORE_CONFIG_NIL)    /* call right on creation if prop exists and has val */
+      listener(key, e->type, tag, data);
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/**
+ * Removes a listener callback.
+ * @param  name     Name of the callback to remove.
+ * @param  key      The property key the callback is listening to.
+ * @param  listener The callback function to remove.
+ * @return @c ECORE_CONFIG_ERR_SUCC if successful in removing the callback.
+ *         If no callback matches the given parameters, then
+ *         @c ECORE_CONFIG_ERR_NOTFOUND is returned.  If @c NULL is passed
+ *         for the key pointer, @c ECORE_CONFIG_ERR_NODATA is returned.
+ * @ingroup Ecore_Config_Listeners_Group
+ */
+EAPI int
+ecore_config_deaf(const char *name, const char *key,
+                 Ecore_Config_Listener listener)
+{
+   Ecore_Config_Prop  *e;
+   Ecore_Config_Listener_List *l, *p;
+   int                 ret;
+
+   ret = ECORE_CONFIG_ERR_NOTFOUND;
+
+   if (!key)
+      return ECORE_CONFIG_ERR_NODATA;
+
+   if (!(e = ecore_config_get(key)))
+      return ECORE_CONFIG_ERR_NOTFOUND;
+
+   for (p = NULL, l = e->listeners; l; p = l)
+     {
+       Ecore_Config_Listener_List *nl;
+       
+       nl = l->next;
+       if ((name && !strcmp(l->name, name)) || (l->listener == listener))
+         {
+            ret = ECORE_CONFIG_ERR_SUCC;
+            if (!p)
+               e->listeners = e->listeners->next;
+            else
+               p->next = l->next;
+            memset(l, 0, sizeof(Ecore_Config_Listener));
+            free(l);
+         }
+       l = nl;
+     }
+
+   return ret;
+}
+
+/**
+ * Locates the first configuration bundle on the given server.
+ * @param  srv The configuration server.
+ * @return Pointer to the first configuration bundle.
+ */
+EAPI Ecore_Config_Bundle *
+ecore_config_bundle_1st_get(Ecore_Config_Server * srv)
+{                              /* anchor: global, but read-only */
+   return srv->bundles;
+}
+
+/**
+ * Locates the configuration bundle after the given one.
+ * @param  ns  The configuration bundle.
+ * @return The next configuration bundle.
+ */
+EAPI Ecore_Config_Bundle *
+ecore_config_bundle_next_get(Ecore_Config_Bundle * ns)
+{
+   return ns ? ns->next : NULL;
+}
+
+/**
+ * Locates a configuration bundle on a configuration server based on its serial
+ * number.
+ * @param  srv    The configuration server.
+ * @param  serial Serial number.
+ * @return The configuration bundle with the given serial number.
+ */
+EAPI Ecore_Config_Bundle *
+ecore_config_bundle_by_serial_get(Ecore_Config_Server * srv, long serial)
+{
+   Ecore_Config_Bundle *eb;
+
+   eb = srv->bundles;
+
+   if (serial < 0)
+      return NULL;
+   else if (serial == 0)
+     {
+       Ecore_Config_Bundle *r = eb;
+
+       return r;
+     }
+
+   while (eb)
+     {
+       if (eb->serial == serial)
+          return eb;
+       eb = eb->next;
+     }
+   return NULL;
+}
+
+/**
+ * Gets the Ecore_Config_Bundle with the given identifier from the given
+ * server.
+ * @param  srv   The configuration server.
+ * @param  label The bundle's identifier string.
+ * @return The bundle with the given identifier string, or @c NULL if it
+ *         could not be found.
+ */
+EAPI Ecore_Config_Bundle *
+ecore_config_bundle_by_label_get(Ecore_Config_Server * srv, const char *label)
+{
+   Ecore_Config_Bundle *ns;
+
+   ns = srv->bundles;
+
+   while (ns)
+     {
+       if (ns->identifier && !strcmp(ns->identifier, label))
+          return ns;
+       ns = ns->next;
+     }
+   return NULL;
+}
+
+/**
+ * Retrieves the bundle's serial number.
+ * @param  ns The configuration bundle.
+ * @return The bundle's identifier string, or -1 if ns is @c NULL.
+ */
+EAPI long
+ecore_config_bundle_serial_get(Ecore_Config_Bundle * ns)
+{
+   return ns ? ns->serial : -1;
+}
+
+/**
+ * Retrieves the bundle's identifier.
+ * @param  ns The configuration bundle.
+ * @return The bundle's identifer string.
+ */
+EAPI char               *
+ecore_config_bundle_label_get(Ecore_Config_Bundle * ns)
+{
+   return ns ? ns->identifier : NULL;
+}
+
+/**
+ * Creates a new Ecore_Config_Bundle.
+ * @param  srv        Config server.
+ * @param  identifier Identifier string for the new bundle.
+ * @return A pointer to a new Ecore_Config_Bundle.  @c NULL is returned if the
+ *         structure couldn't be allocated.
+ */
+EAPI Ecore_Config_Bundle *
+ecore_config_bundle_new(Ecore_Config_Server * srv, const char *identifier)
+{
+   Ecore_Config_Bundle *t;
+   static long         ss;
+
+   ss = 0;                     /* bundle unique serial */
+
+   if ((t = malloc(sizeof(Ecore_Config_Bundle))))
+     {
+       memset(t, 0, sizeof(Ecore_Config_Bundle));
+
+       t->identifier = (char *)identifier;
+       t->serial = ++ss;
+       t->owner = srv->name;
+       t->next = srv->bundles;
+       srv->bundles = t;
+     }
+   return t;
+}
+
+static Ecore_Config_Server *
+do_init(const char *name)
+{
+   return _ecore_config_ipc_init(name);
+}
+
+static Ecore_Config_Server *
+ecore_config_init_local(const char *name)
+{
+   char               *p;
+   char               *buf;
+
+   if ((p = getenv("HOME")))
+     {                         /* debug-only ### FIXME */
+       if (!(buf = malloc(PATH_MAX * sizeof(char))))
+          return NULL;
+       snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name);
+       unlink(buf);
+
+       free(buf);
+     }
+
+   return do_init(name);
+}
+
+static Ecore_Config_Server *
+ecore_config_init_global(const char *name)
+{
+   char               *p;
+   int global;
+   char               *buf;
+
+   if ((p = getenv("HOME")))
+     {                         /* debug-only ### FIXME */
+       if (!(buf = malloc(PATH_MAX * sizeof(char))))
+          return NULL;
+       snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name);
+       global = creat(buf, S_IRWXU);
+
+       if (global)
+          close(global);
+
+       free(buf);
+     }
+
+   return do_init(name);
+}
+
+/**
+ * @defgroup Ecore_Config_App_Lib_Group Ecore Config App Library Functions
+ *
+ * Functions that are used to start up and shutdown the Enlightened
+ * Property Library when used directly by an application.
+ */
+
+/**
+ * Initializes the Enlightened Property Library.
+ *
+ * Either this function or @ref ecore_config_system_init must be run
+ * before any other function in the Enlightened Property Library, even
+ * if you have run @ref ecore_init .  The name given is used to
+ * determine the default configuration to load.
+ *
+ * @param  name Application name
+ * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up.
+ *         @c ECORE_CONFIG_ERR_FAIL otherwise.
+ * @ingroup Ecore_Config_App_Lib_Group
+ */
+EAPI int
+ecore_config_init(const char *name)
+{
+   char                *path;
+   Ecore_Config_Prop   *list;
+   _ecore_config_log_dom = eina_log_domain_register("EcoreConfig", ECORE_CONFIG_DEFAULT_LOG_COLOR);
+   if(_ecore_config_log_dom < 0) 
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the Ecore config module.");
+       return -1;
+     }
+   _ecore_config_system_init_no_load();
+
+   __ecore_config_app_name = strdup(name);
+   __ecore_config_server_local = ecore_config_init_local(name);
+   if (!__ecore_config_server_local)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   list = __ecore_config_bundle_local->data;
+   free( __ecore_config_bundle_local );
+   __ecore_config_bundle_local =
+      ecore_config_bundle_new(__ecore_config_server_local, "config");
+   __ecore_config_bundle_local->data = list;
+
+   path = ecore_config_theme_default_path_get();
+   ecore_config_string_default("/e/themes/search_path", path);
+   if (path)
+      free(path);
+
+   list = ecore_config_get("/e/themes/search_path");
+   if (list)
+     {
+       list->flags |= ECORE_CONFIG_FLAG_SYSTEM;
+       list->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
+     }
+
+   return _ecore_config_system_load();
+}
+
+/**
+ * Frees memory and shuts down the library for an application.
+ * @return @c ECORE_CONFIG_ERR_IGNORED .
+ * @ingroup Ecore_Config_App_Lib_Group
+ */
+EAPI int
+ecore_config_shutdown(void)
+{
+   return ecore_config_system_shutdown();
+}
+
+/**
+ * @defgroup Ecore_Config_Lib_Lib_Group Ecore Config Library Functions
+ *
+ * Functions that are used to start up and shutdown the Enlightened
+ * Property Library when used directly by an application.
+ */
+
+/**
+ * Initializes the Enlightened Property Library.
+ *
+ * This function is meant to be run from other programming libraries.
+ * It should not be called from applications.
+ *
+ * This function (or @ref ecore_config_init )
+ * must be run before any other function in the
+ * Enlightened Property Library, even if you have run @ref ecore_init .
+ *
+ * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up.
+ *         @c ECORE_CONFIG_ERR_FAIL otherwise.
+ * @ingroup Ecore_Config_Lib_Lib_Group
+ */
+EAPI int
+ecore_config_system_init(void)
+{
+   _ecore_config_system_init_no_load();
+   return _ecore_config_system_load();
+}
+
+static            int
+_ecore_config_system_init_no_load(void)
+{
+   char               *p;
+
+   __ecore_config_system_init++;
+   if (__ecore_config_system_init > 1)
+      return ECORE_CONFIG_ERR_IGNORED;
+
+   DEBUG = -1;
+   if ((p = getenv("ECORE_CONFIG_DEBUG")) && p[0] != 0)
+     {
+       DEBUG = atoi(p);
+     }
+
+   __ecore_config_server_global =
+      ecore_config_init_global(ECORE_CONFIG_GLOBAL_ID);
+   if (!__ecore_config_server_global)
+       return ECORE_CONFIG_ERR_FAIL;
+
+   __ecore_config_bundle_local =
+      ecore_config_bundle_new(__ecore_config_server_global, "system");
+
+   /* set up a simple default path */
+   ecore_config_string_default("/e/themes/search_path", PACKAGE_DATA_DIR "../ewl/themes");
+   
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+
+static             int
+_ecore_config_system_load(void)
+{
+   char               *buf, *p;
+   Ecore_Config_Prop  *sys;
+
+   if (__ecore_config_system_init != 1)
+       return ECORE_CONFIG_ERR_FAIL;
+
+   if ((p = getenv("HOME")))
+     {                          /* debug-only ### FIXME */
+       if ((buf = malloc(PATH_MAX * sizeof(char))))
+         {
+            snprintf(buf, PATH_MAX, "%s/.e/config.eet", p);
+            if (ecore_config_file_load(buf) != 0) {
+               /* even if this file (system.eet) dosen't exist we can 
+                * continue without it as it isn't striclty necessary.
+               */
+               ecore_config_file_load(PACKAGE_DATA_DIR "/system.eet");
+            }
+            sys = __ecore_config_bundle_local->data;
+            while (sys)
+              {
+                 /* unmark it modified - modification will mean it has been overridden */
+                 sys->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
+                 /* mark as system so that examine can hide them */
+                 sys->flags |= ECORE_CONFIG_FLAG_SYSTEM;
+                 sys = sys->next;
+              }
+         }
+       free(buf);
+     }
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+
+/**
+ * Frees memory and shuts down the library for other programming libraries.
+ * @return @c ECORE_CONFIG_ERR_IGNORED
+ * @ingroup Ecore_Config_Lib_Lib_Group
+ */
+EAPI int
+ecore_config_system_shutdown(void)
+{
+   int                 ret;
+
+   __ecore_config_system_init--;
+   if (__ecore_config_system_init > 0)
+      return ECORE_CONFIG_ERR_IGNORED;
+
+   ret = _ecore_config_ipc_exit();
+   if (__ecore_config_app_name)
+      free(__ecore_config_app_name);
+   while(__ecore_config_bundle_local->data)
+     ecore_config_dst(__ecore_config_bundle_local->data);
+   free(__ecore_config_bundle_local);
+   free(__ecore_config_server_local);
+   free(__ecore_config_server_global);
+   eina_log_domain_unregister(_ecore_config_log_dom);
+   _ecore_config_log_dom = -1;
+   return ret;
+}
+
+static inline void *
+__ecore_argb_to_long(int a, int r, int g, int b, long *v)
+{
+   *v = ((a << 24) & 0xff000000 )
+      | ((r << 16) &   0xff0000 )
+      | ((g <<  8) &     0xff00 )
+      | ( b        &       0xff );
+
+   return v;
+}
+
+static inline void *
+__ecore_argbstr_to_long(const char *argb, long *v)
+{
+   char *l = NULL;
+
+   // convert hexadecimal string #..., #0x..., 0x..., ... to long
+   if(*argb == '#')
+     argb++;
+   *v = (long)strtoul( argb, &l, 16);
+
+   if(*l)
+     {
+       ERR("ecore_config_val: value \"%s\" not a valid hexadecimal RGB value?", argb);
+       return NULL;
+     }
+
+   return v;
+}
+
diff --git a/src/lib/ecore_config/ecore_config_db.c b/src/lib/ecore_config/ecore_config_db.c
new file mode 100644 (file)
index 0000000..bb5e12a
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <locale.h>
+
+#include <Eet.h>
+
+#include "Ecore_Config.h"
+#include "ecore_config_private.h"
+#include "ecore_config_util.h"
+
+struct _Ecore_Config_DB_File
+{
+   Eet_File *ef;
+};
+
+Ecore_Config_DB_File *
+_ecore_config_db_open_read(const char *file)
+{
+   Eet_File *ef;
+   Ecore_Config_DB_File *db;
+   
+   eet_init();
+   db = malloc(sizeof(Ecore_Config_DB_File));
+   if (!db) return NULL;
+   ef = eet_open((char*)file, EET_FILE_MODE_READ);
+   if (!ef)
+     {
+       free(db);
+       return NULL;
+     }
+   db->ef = ef;
+   return db;
+}
+
+Ecore_Config_DB_File *
+_ecore_config_db_open_write(const char *file)
+{
+   Eet_File *ef;
+   Ecore_Config_DB_File *db;
+   
+   eet_init();
+   db = malloc(sizeof(Ecore_Config_DB_File));
+   if (!db) return NULL;
+   ef = eet_open((char*)file, EET_FILE_MODE_WRITE);
+   if (!ef)
+     {
+       free(db);
+       return NULL;
+     }
+   db->ef = ef;
+   return db;
+}
+
+void
+_ecore_config_db_close(Ecore_Config_DB_File *db)
+{
+   eet_close(db->ef);
+   free(db);
+   eet_shutdown();
+}
+
+char **
+_ecore_config_db_keys_get(Ecore_Config_DB_File *db, int *num_ret)
+{
+   char **keys;
+   int key_count;
+   int i;
+   
+   keys = eet_list(db->ef, (char*)"*", &key_count);
+   if (!keys)
+     {
+       *num_ret = 0;
+       return NULL;
+     }
+   /* make keys freeable - this is safe to do */
+   for (i = 0; i < key_count; i++) keys[i] = strdup(keys[i]);
+   *num_ret = key_count;
+   return keys;
+}
+
+Ecore_Config_Type
+_ecore_config_db_key_type_get(Ecore_Config_DB_File *db, const char *key)
+{
+   char *data;
+   int size;
+   
+   data = eet_read(db->ef, (char*)key, &size);
+   if (data)
+     {
+       if (size <= 2)
+         {
+            free(data);
+            return ECORE_CONFIG_NIL;
+         }
+       if (data[size - 1] != 0)
+         {
+            free(data);
+            return ECORE_CONFIG_NIL;
+         }
+       return (Ecore_Config_Type) data[0];
+     }
+   return ECORE_CONFIG_NIL;
+}
+
+int
+_ecore_config_db_read(Ecore_Config_DB_File *db, const char *key)
+{
+   char *data, *value;
+   int size;
+   Ecore_Config_Type type;
+   
+   data = eet_read(db->ef, (char*)key, &size);
+   if (data)
+     {
+       int l;
+       char *prev_locale;
+
+       if (size <= 2)
+         {
+            free(data);
+            return 0;
+         }
+       if (data[size - 1] != 0)
+         {
+            free(data);
+            return 0;
+         }
+       /* "type" NIL 1242 NIL */
+       l = strlen(data);
+       if (l >= (size - 1))
+         {
+            free(data);
+            return 0;
+         }
+   
+       type = data[0];
+       value = data + l + 1;
+
+       switch (type) 
+         {
+            case ECORE_CONFIG_INT:
+            case ECORE_CONFIG_BLN:
+              {
+                 int tmp;
+                 prev_locale = setlocale(LC_NUMERIC, "C");
+                 tmp = atoi(value);
+                 if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+
+                 ecore_config_typed_set(key, (void *)&tmp, type);
+                 break;
+              }
+            case ECORE_CONFIG_FLT:
+              {
+                 float tmp;
+                 prev_locale = setlocale(LC_NUMERIC, "C");
+                 tmp = atof(value);
+                 if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+              
+                 ecore_config_typed_set(key, (void *)&tmp, type);
+                 break;
+              }
+            case ECORE_CONFIG_RGB:
+              ecore_config_argbstr_set(key, value);
+              break;
+            case ECORE_CONFIG_STR:
+            case ECORE_CONFIG_THM:
+              ecore_config_typed_set(key, (void *)value, type);
+              break;
+            case ECORE_CONFIG_SCT:
+              INF("loading struct %s", key);
+              break;
+            default:
+              WRN("Type %d not handled", type);
+         }
+       free(data);
+       return 1;
+     }
+   return 0;
+}
+
+/*
+void *
+_ecore_config_db_key_data_get(Ecore_Config_DB_File *db, const char *key, int *size_ret)
+{
+   char *data;
+   int size;
+   
+   data = eet_read(db->ef, (char*)key, &size);
+   if (data)
+     {
+       int l;
+       char *dat;
+       
+       if (size <= 2)
+         {
+            free(data);
+            return NULL;
+         }
+       if (data[size - 1] != 0)
+         {
+            free(data);
+            return NULL;
+         }
+       * "type" NIL data_goes_here NIL *
+       l = strlen(data);
+       if (l >= (size - 1))
+         {
+            free(data);
+            return NULL;
+         }
+       dat = malloc(size - (l + 2));
+       memcpy(dat, data + l + 1, size - (l + 2));
+       free(data);
+       *size_ret = size - (l + 2);
+       return dat;
+     }
+   return NULL;
+}*/
+
+void
+_ecore_config_db_write(Ecore_Config_DB_File *db, Ecore_Config_Prop *e)
+{
+   char *prev_locale= NULL;
+   char *val = NULL;
+   char *r = NULL;
+   int num;
+   
+   prev_locale = setlocale(LC_NUMERIC, "C");
+
+   switch (e->type) 
+     {
+       case ECORE_CONFIG_INT:
+          esprintf(&val, "%i", _ecore_config_int_get(e));
+          break;
+       case ECORE_CONFIG_BLN:
+          esprintf(&val, "%i", _ecore_config_boolean_get(e));
+          break;
+       case ECORE_CONFIG_FLT:
+          esprintf(&val, "%16.16f", _ecore_config_float_get(e));
+          break;
+       case ECORE_CONFIG_STR: 
+          val = _ecore_config_string_get(e);
+          break;
+       case ECORE_CONFIG_THM:
+          val = _ecore_config_theme_get(e);
+          break;
+       case ECORE_CONFIG_RGB:
+          val = _ecore_config_argbstr_get(e);
+          break;
+       default:
+          WRN("Type %d not handled", e->type);
+     }
+
+   if (prev_locale)
+     {
+       setlocale(LC_NUMERIC, prev_locale);
+     }
+   
+   if(val)
+     {
+       num = esprintf(&r, "%c%c%s%c", (char) e->type, 0, val, 0);
+       if(num)
+         eet_write(db->ef, e->key, r, num, 1);
+       free(r);
+     }
+
+   free(val);
+}
+/*
+void
+_ecore_config_db_key_data_set(Ecore_Config_DB_File *db, const char *key, void *data, int data_size)
+{
+   char *buf;
+   int num;
+   
+   num = 1 + 1 + data_size + 1;
+   buf = malloc(num);
+   if (!buf) return;
+   buf[0] = (char) ECORE_CONFIG_BIN;
+   buf[1] = 0;
+   memcpy(buf + 2, data, data_size);
+   buf[num - 1] = 0;
+   eet_write(db->ef, (char*)key, buf, num, 1);
+   free(buf);
+}*/
diff --git a/src/lib/ecore_config/ecore_config_extra.c b/src/lib/ecore_config/ecore_config_extra.c
new file mode 100644 (file)
index 0000000..10d22a6
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "Ecore_Config.h"
+#include "Ecore.h"
+#include "ecore_config_private.h"
+typedef struct __Ecore_Config_Arg_Callback _Ecore_Config_Arg_Callback;
+struct __Ecore_Config_Arg_Callback
+{
+   char                  short_opt;
+   char                 *long_opt;
+   char                 *description;
+   void                 *data;
+   void                (*func)(char *val, void *data);
+   Ecore_Config_Type type;
+   _Ecore_Config_Arg_Callback *next;
+};
+
+char               *__ecore_config_app_description;
+_Ecore_Config_Arg_Callback *_ecore_config_arg_callbacks;
+
+/* shorthand prop setup code to make client apps a little smaller ;) */
+
+/**
+ * Creates a new property, if it does not already exist, and sets its
+ * attributes to those given.
+ *
+ * The type of the property is guessed from the key and the value
+ * given.
+ *
+ * @param   key       The property key.
+ * @param   val       Pointer to default value of key.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_create(const char *key, void *val, char short_opt, char *long_opt,
+                   char *desc)
+{
+   int                 type = ecore_config_type_guess(key, val);
+
+   return ecore_config_typed_create(key, val, type, short_opt, long_opt, desc);
+}
+
+/**
+ * Creates a new property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Pointer to default value of key.
+ * @param   type      Type of the property.
+ * @param   short_opt Short option used to set the property from
+ *                    command line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_typed_create(const char *key, void *val, int type, char short_opt,
+                         char *long_opt, char *desc)
+{
+   int                 ret;
+
+   if ((ret =
+       ecore_config_typed_default(key, val, type)) != ECORE_CONFIG_ERR_SUCC)
+      return ret;
+   if ((ret =
+       ecore_config_short_opt_set(key, short_opt)) != ECORE_CONFIG_ERR_SUCC)
+      return ret;
+   if ((ret =
+       ecore_config_long_opt_set(key, long_opt)) != ECORE_CONFIG_ERR_SUCC)
+      return ret;
+   ret = ecore_config_describe(key, desc);
+   return ret;
+}
+
+/**
+ * Creates a new boolean property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default boolean value of key.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_boolean_create(const char *key, int val, char short_opt,
+                       char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_BLN, short_opt, long_opt,
+                               desc);
+}
+
+/**
+ * Creates a new integer property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default integer value of key.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_int_create(const char *key, int val, char short_opt,
+                       char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_INT, short_opt, long_opt,
+                               desc);
+}
+
+/**
+ * Creates a new integer property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default integer value of key.
+ * @param   low       Lowest valid integer value for the property.
+ * @param   high      Highest valid integer value for the property.
+ * @param   step      Increment value for the property.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_int_create_bound(const char *key, int val, int low, int high,
+                             int step, char short_opt, char *long_opt,
+                             char *desc)
+{
+   Ecore_Config_Prop  *e;
+   int                 ret;
+
+   ret =
+      ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_INT, short_opt, long_opt,
+                               desc);
+   if (ret != ECORE_CONFIG_ERR_SUCC)
+      return ret;
+   e = ecore_config_get(key);
+   if (e)
+     {
+       e->step = step;
+       e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+       e->lo = low;
+       e->hi = high;
+       ecore_config_bound(e);
+     }
+   return ret;
+}
+
+/**
+ * Creates a new string property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default value of key.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_string_create(const char *key, char *val, char short_opt,
+                          char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_STR, short_opt, long_opt,
+                               desc);
+}
+
+/**
+ * Creates a new float property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default float value of key.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_float_create(const char *key, float val, char short_opt,
+                         char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_FLT, short_opt, long_opt,
+                               desc);
+}
+
+/**
+ * Creates a new float property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default float value of key.
+ * @param   low       Lowest valid float value for the property.
+ * @param   high      Highest valid float value for the property.
+ * @param   step      Increment value for the property.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_float_create_bound(const char *key, float val, float low,
+                               float high, float step, char short_opt,
+                               char *long_opt, char *desc)
+{
+   Ecore_Config_Prop  *e;
+   int                 ret;
+
+   ret =
+      ecore_config_typed_create(key, (void *)&val, ECORE_CONFIG_FLT, short_opt, long_opt,
+                               desc);
+   e = ecore_config_get(key);
+   if (e)
+     {
+       e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION);
+       e->flags |= ECORE_CONFIG_FLAG_BOUNDS;
+       e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION);
+       e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION);
+       ecore_config_bound(e);
+     }
+   return ret;
+}
+
+/**
+ * Creates a new color property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default color value of key, as a hexadecimal string.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_argb_create(const char *key, char *val, char short_opt,
+                       char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_RGB, short_opt, long_opt,
+                               desc);
+}
+
+/**
+ * Creates a new theme property, if it does not already exist, and sets its
+ * attributes to those given.
+ * @param   key       The property key.
+ * @param   val       Default theme name for the property.
+ * @param   short_opt Short option used to set the property from command
+ *                    line.
+ * @param   long_opt  Long option used to set the property from command line.
+ * @param   desc      String description of property.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.
+ * @ingroup Ecore_Config_Create_Group
+ */
+int
+ecore_config_theme_create(const char *key, char *val, char short_opt,
+                         char *long_opt, char *desc)
+{
+   return
+      ecore_config_typed_create(key, (void *)val, ECORE_CONFIG_THM, short_opt, long_opt,
+                               desc);
+}
+
+/* this should only be built if evas is present */
+
+/**
+ * Calls evas_font_path_append on @p evas for each of the font names stored
+ * in the property "/e/font/path".
+ * @param  evas Evas object to append the font names to.
+ * @return @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
+ *         is returned if the property has not been set.
+ */
+int
+ecore_config_evas_font_path_apply(Evas * evas)
+{
+   char               *font_path, *font_path_tmp, *ptr, *end;
+
+   font_path = ecore_config_string_get("/e/font/path");
+
+   if (!font_path)
+      return ECORE_CONFIG_ERR_NODATA;
+   ptr = font_path;
+   end = font_path + strlen(font_path);
+   font_path_tmp = font_path;
+   while (ptr && ptr < end)
+     {
+       while (*ptr != '|' && ptr < end)
+          ptr++;
+       if (ptr < end)
+          *ptr = '\0';
+
+       evas_font_path_append(evas, font_path_tmp);
+       ptr++;
+       font_path_tmp = ptr;
+     }
+
+   free(font_path);
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/**
+ * Retrieves the default theme search path.
+ *
+ * @return The default theme search path.
+ */
+char               *
+ecore_config_theme_default_path_get(void)
+{
+   char               *path, *home;
+   int                 len;
+
+   home = getenv("HOME");
+   len = strlen(PACKAGE_DATA_DIR "/../") + strlen(__ecore_config_app_name) +
+            strlen("/themes/") + 1;
+   if (home)
+      len += strlen(home) + strlen("/.e/apps/") +
+               strlen(__ecore_config_app_name) +
+               strlen("/themes/|"); /* no \0, as that is above */
+
+   if (!(path = malloc(len)))
+      return NULL;
+
+   *path = '\0';
+   if (home)
+     {
+        strcat(path, home);
+        strcat(path, "/.e/apps/");
+        strcat(path, __ecore_config_app_name);
+        strcat(path, "/themes/|");
+     }
+   strcat(path, PACKAGE_DATA_DIR "/../");
+   strcat(path, __ecore_config_app_name);
+   strcat(path, "/themes/");
+
+   return path;
+}
+
+/**
+ * Retrieves the search path used to find themes.
+ *
+ * The search path is stored in the property "/e/themes/search_path".  If
+ * the property has not been set, the default path used is
+ * "/usr/local/share/<app_name>/themes|~/.e/apps/<app_name>/themes".
+ * See @ref ecore_config_theme_default_path_get for more information about
+ * the default path.
+ *
+ * @return The search path.  @c NULL is returned if there is no memory left.
+ */
+char               *
+ecore_config_theme_search_path_get(void)
+{
+   char               *search_path;
+   search_path = ecore_config_string_get("/e/themes/search_path");
+
+   /* this should no longer be the case, as it is defaulted in init */
+   if (!search_path)
+     {
+       search_path = ecore_config_theme_default_path_get();
+       if (search_path)
+         {
+            ecore_config_string_default("/e/themes/search_path", search_path);
+            free(search_path);
+         }
+     }
+   return search_path;
+}
+
+/**
+ * Adds the given path to the search path used to find themes.
+ *
+ * If the search path is successfully, the new search path will be saved
+ * into the property "/e/themes/search_path".  Therefore, this function
+ * should be called @b after @ref ecore_config_load to allow a user to
+ * override the default search path.
+ *
+ * @param  path The given 
+ * @return @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_FAIL
+ *         will be returned if @p path already exists in the search path.
+ *         @c ECORE_CONFIG_ERR_FAIL is returned if @p path is @c NULL.
+ */
+int
+ecore_config_theme_search_path_append(const char *path)
+{
+   char               *search_path, *loc, *new_search_path;
+   int                 len, search_len;
+   Ecore_Config_Prop  *prop;
+
+   if (!path)
+     return ECORE_CONFIG_ERR_NODATA;
+   search_path = ecore_config_theme_search_path_get();
+
+   loc = strstr(search_path, path);
+   len = strlen(path);
+   search_len = strlen(search_path);
+   
+   if (loc == NULL || (loc != search_path && *(loc - 1) != '|') || 
+       (loc != (search_path + search_len - len) && *(loc + len - 1) != '|'))
+     {
+       new_search_path = malloc(search_len + len + 2); /* 2 = \0 + | */
+       strcpy(new_search_path, search_path);
+       strncat(new_search_path, "|", 1);
+       strncat(new_search_path, path, len);
+
+       ecore_config_string_set("/e/themes/search_path", new_search_path);
+       prop = ecore_config_get("/e/themes/search_path");
+       if (prop)
+         prop->flags &= ~ECORE_CONFIG_FLAG_MODIFIED;
+
+       free(new_search_path);
+
+       return ECORE_CONFIG_ERR_SUCC;
+     }
+   return ECORE_CONFIG_ERR_FAIL;
+}
+
+/**
+ * Retrieve a theme file's full path.
+ *
+ * The search path for theme files is given by @ref
+ * ecore_config_theme_search_path_get .
+ *
+ * @param  name The name of the theme.
+ * @return A full path to the theme on success.  @c NULL will be returned
+ *         if @p name is @c NULL or no theme matching the given name could
+ *         be found.
+ */
+char               *
+ecore_config_theme_with_path_from_name_get(char *name)
+{
+   char               *search_path, *search_path_tmp, *ptr, *end, *file;
+   struct stat         st;
+
+   if (!name)
+      return NULL; /* no theme specified (nor a default) */
+
+   search_path = ecore_config_theme_search_path_get();
+   ptr = search_path;
+   end = search_path + strlen(search_path);
+   search_path_tmp = search_path;
+   while (ptr && ptr < end)
+     {
+        while (*ptr != '|' && ptr < end)
+           ptr++;
+        if (ptr < end)
+           *ptr = '\0';
+
+        file = malloc(strlen(search_path_tmp) + strlen(name) + 6);
+           /* 6 = / + .edj + \0 */
+
+        snprintf(file, strlen(search_path_tmp) + strlen(name) + 6, 
+                      "%s/%s.edj", search_path_tmp, name);
+       
+        if (stat(file, &st) == 0)
+          {
+              free(search_path);
+              return file;
+          }
+        free(file);
+        ptr++;
+        search_path_tmp = ptr;
+     }
+
+   free(search_path);
+
+   return NULL; /* we could not find the theme with that name in search path */
+}
+
+/**
+ * Retrieves the full path to the theme file of the theme stored in the
+ * given property.
+ *
+ * The search path for themes is given by @ref
+ * ecore_config_theme_search_path_get .
+ *
+ * @param  key The given property.
+ * @return A full path to the theme on success, or @c NULL on failure.
+ *         This function will fail if no key is specified or not theme
+ *         matching that given by the property @p key could be found.
+ */
+char               *
+ecore_config_theme_with_path_get(const char *key)
+{
+   return
+      ecore_config_theme_with_path_from_name_get(ecore_config_theme_get(key));
+}
+
+static const char  *_ecore_config_short_types[] =
+   { "      ", "<int> ", "<flt> ", "<str> ", "<rgb> ", "<str> ", "<bool>" };
+
+/**
+ * Prints the property list of the local configuration bundle to output.
+ */
+void
+ecore_config_args_display(void)
+{
+   Ecore_Config_Prop  *props;
+   _Ecore_Config_Arg_Callback *callbacks;
+
+   if (__ecore_config_app_description)
+      ERR("%s\n\n", __ecore_config_app_description);
+   ERR("Supported Options:");
+   ERR(" -h, --help\t       Print this text");
+   if (!__ecore_config_bundle_local)
+      return;
+   props = __ecore_config_bundle_local->data;
+   while (props)
+     {
+       /* if it is a system prop, or cannot be set on command line hide it */
+       if (props->flags & ECORE_CONFIG_FLAG_SYSTEM || (!props->short_opt && !props->long_opt))
+         {
+            props = props->next;
+            continue;
+         }
+       INF(" %c%c%c --%s\t%s %s", props->short_opt ? '-' : ' ',
+              props->short_opt ? props->short_opt : ' ',
+              props->short_opt ? ',' : ' ',
+              props->long_opt ? props->long_opt : props->key,
+              _ecore_config_short_types[props->type],
+              props->description ? props->description :
+              "(no description available)");
+
+       props = props->next;
+     }
+   callbacks = _ecore_config_arg_callbacks;
+   while (callbacks)
+     {
+        INF(" %c%c%c --%s\t%s %s", callbacks->short_opt ? '-' : ' ',
+              callbacks->short_opt ? callbacks->short_opt : ' ',
+              callbacks->short_opt ? ',' : ' ',
+              callbacks->long_opt ? callbacks->long_opt : "",
+               _ecore_config_short_types[callbacks->type],
+              callbacks->description ? callbacks->description :
+              "(no description available)");
+
+       callbacks = callbacks->next;
+     }
+}
+
+static int
+ecore_config_parse_set(Ecore_Config_Prop * prop, char *arg, char *opt,
+                      char opt2)
+{
+   if (!arg)
+     {
+       if (opt)
+          ERR("Missing expected argument for option --%s", opt);
+       else
+          ERR("Missing expected argument for option -%c", opt2);
+       return ECORE_CONFIG_PARSE_EXIT;
+     }
+   else
+     {
+       ecore_config_set(prop->key, arg);
+       prop->flags |= ECORE_CONFIG_FLAG_CMDLN;
+     }   
+   return ECORE_CONFIG_PARSE_CONTINUE;
+}
+
+static void
+ecore_config_args_callback_add(char short_opt, char *long_opt, char *desc,
+                              void (*func)(char *val, void *data),
+                              void *data, Ecore_Config_Type type) {
+   _Ecore_Config_Arg_Callback *new_cb;
+
+   new_cb = malloc(sizeof(_Ecore_Config_Arg_Callback));
+   new_cb->short_opt = short_opt;
+   if (long_opt)
+      new_cb->long_opt = strdup(long_opt);
+   if (desc)
+      new_cb->description = strdup(desc);
+   new_cb->data = data;
+   new_cb->func = func;
+   new_cb->type = type;
+
+   new_cb->next = _ecore_config_arg_callbacks;
+   _ecore_config_arg_callbacks = new_cb;
+}
+
+void
+ecore_config_args_callback_str_add(char short_opt, char *long_opt, char *desc,
+                                  void (*func)(char *val, void *data),
+                                  void *data) {
+   ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, ECORE_CONFIG_STR);
+}
+
+void
+ecore_config_args_callback_noarg_add(char short_opt, char *long_opt, char *desc,
+                                    void (*func)(char *val, void *data),
+                                    void *data) {
+   ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, ECORE_CONFIG_NIL);
+}
+
+/**
+ * Parse the arguments set by @ref ecore_app_args_set and set properties
+ * accordingly.
+ *
+ * @return @c ECORE_CONFIG_PARSE_CONTINUE if successful.
+ *         @c ECORE_CONFIG_PARSE_EXIT is returned if an unrecognised option
+ *         is found.  @c ECORE_CONFIG_PARSE_HELP is returned if help was
+ *         displayed.
+ */
+int
+ecore_config_args_parse(void)
+{
+   int                 argc;
+   char              **argv;
+   int                 nextarg, next_short_opt, found, ret;
+   char               *arg;
+   char               *long_opt, short_opt;
+   Ecore_Config_Prop  *prop;
+   _Ecore_Config_Arg_Callback *callback;
+
+   ecore_app_args_get(&argc, &argv);
+   nextarg = 1;
+   while (nextarg < argc)
+     {
+       arg = argv[nextarg];
+
+       if (*arg != '-')
+         {
+            ERR("Unexpected attribute \"%s\"", arg);
+            nextarg++;
+            continue;
+         }
+
+       next_short_opt = 1;
+       short_opt = *(arg + next_short_opt);
+
+       if (short_opt == '-')
+         {
+            long_opt = arg + 2;
+
+            if (!strcmp(long_opt, "help"))
+              {
+                 ecore_config_args_display();
+                 return ECORE_CONFIG_PARSE_HELP;
+              }
+
+            found = 0;
+            prop = __ecore_config_bundle_local->data;
+            while (prop)
+              {
+                 if ((prop->long_opt && !strcmp(long_opt, prop->long_opt))
+                     || !strcmp(long_opt, prop->key))
+                   {
+                      found = 1;
+                      if ((ret =
+                           ecore_config_parse_set(prop, argv[++nextarg],
+                                                  long_opt,
+                                                  '\0')) !=
+                          ECORE_CONFIG_PARSE_CONTINUE)
+                         return ret;
+                      break;
+                   }
+                 prop = prop->next;
+              }
+            if (!found)
+              {
+                 callback = _ecore_config_arg_callbacks;
+                 while (callback)
+                   {
+                      if ((callback->long_opt && 
+                           !strcmp(long_opt, callback->long_opt)))
+                        {
+                           found = 1;
+                           if (callback->type == ECORE_CONFIG_NIL)
+                             {
+                                callback->func(NULL, callback->data);
+                             }
+                           else 
+                             {
+                                if (!argv[++nextarg])
+                                  {
+                                     ERR("Missing expected argument for option --%s", long_opt);
+                                     return ECORE_CONFIG_PARSE_EXIT;
+                                  }
+                                  callback->func(argv[nextarg], callback->data);
+                             }
+                           break;
+                        }
+                      callback = callback->next;
+                   }
+              }
+            if (!found)
+              {
+                 ERR("Unrecognised option \"%s\"", long_opt);
+                 ERR("Try using -h or --help for more information.\n");
+                 return ECORE_CONFIG_PARSE_EXIT;
+              }
+         }
+       else
+         {
+            while (short_opt)
+              {
+                 if (short_opt == 'h')
+                   {
+                      ecore_config_args_display();
+                      return ECORE_CONFIG_PARSE_HELP;
+                   }
+                 else
+                   {
+                      found = 0;
+                      prop = __ecore_config_bundle_local->data;
+                      while (prop)
+                        {
+                           if (short_opt == prop->short_opt)
+                             {
+                                found = 1;
+                                if ((ret =
+                                     ecore_config_parse_set(prop,
+                                                            argv[++nextarg],
+                                                            NULL,
+                                                            short_opt)) !=
+                                    ECORE_CONFIG_PARSE_CONTINUE)
+                                   return ret;
+                                break;
+                             }
+                           prop = prop->next;
+                        }
+
+                      if (!found)
+                        {
+                           callback = _ecore_config_arg_callbacks;
+                           while (callback)
+                             {
+                                if (short_opt == callback->short_opt)
+                                  {
+                                     found = 1;
+                                     if (callback->type == ECORE_CONFIG_NIL)
+                                       {
+                                          callback->func(NULL, callback->data);
+                                       }
+                                     else
+                                       {
+                                          if (!argv[++nextarg])
+                                            {
+                                               ERR("Missing expected argument for option -%c", short_opt);
+                                               return ECORE_CONFIG_PARSE_EXIT;
+                                            }
+                                          callback->func(argv[nextarg], callback->data);
+                                       }
+                                     break;
+                                  }
+                                callback = callback->next;
+                             }
+                        }
+                      if (!found)
+                        {
+                           ERR("Unrecognised option '%c'", short_opt);
+                           ERR("Try using -h or --help for more information.\n");
+                           return ECORE_CONFIG_PARSE_EXIT;
+                        }
+                   }
+                 short_opt = *(arg + ++next_short_opt);
+              }
+         }
+       nextarg++;
+     }
+
+   return ECORE_CONFIG_PARSE_CONTINUE;
+}
+
+/**
+ * Sets the description string used by @ref ecore_config_args_display .
+ * @param description Description of application.
+ */
+void
+ecore_config_app_describe(char *description)
+{
+   if (__ecore_config_app_description)
+      free(__ecore_config_app_description);
+   __ecore_config_app_description = strdup(description);
+}
diff --git a/src/lib/ecore_config/ecore_config_ipc.h b/src/lib/ecore_config/ecore_config_ipc.h
new file mode 100644 (file)
index 0000000..7b3dea1
--- /dev/null
@@ -0,0 +1,50 @@
+#include <Ecore_Ipc.h>
+#include "Ecore_Config.h"
+
+typedef enum
+{
+   IPC_NONE,
+   IPC_PROP_LIST,
+   IPC_PROP_DESC,
+   IPC_PROP_GET,
+   IPC_PROP_SET, /* end of the codes shared by evidence and econf */
+
+   IPC_GLOBAL_PROP_LIST,
+
+   IPC_BUNDLE_LIST,
+   IPC_BUNDLE_NEW,
+   IPC_BUNDLE_LABEL_GET,
+   IPC_BUNDLE_LABEL_SET,
+   IPC_BUNDLE_LABEL_FIND,
+
+   IPC_LAST
+} Ecore_Config_Ipc_Call;
+
+Ecore_Config_Server *_ecore_config_ipc_init(const char *pipe_name);
+int                  _ecore_config_ipc_exit(void);
+
+Ecore_Config_Server *_ecore_config_server_convert(void *srv);
+
+char               *_ecore_config_ipc_prop_list(Ecore_Config_Server * srv,
+                                               const long serial);
+char               *_ecore_config_ipc_prop_desc(Ecore_Config_Server * srv,
+                                               const long serial,
+                                               const char *key);
+char               *_ecore_config_ipc_prop_get(Ecore_Config_Server * srv,
+                                              const long serial,
+                                              const char *key);
+int                 _ecore_config_ipc_prop_set(Ecore_Config_Server * srv,
+                                              const long serial,
+                                              const char *key,
+                                              const char *val);
+
+char               *_ecore_config_ipc_bundle_list(Ecore_Config_Server * srv);
+int                 _ecore_config_ipc_bundle_new(Ecore_Config_Server * srv,
+                                                const char *);
+char               *_ecore_config_ipc_bundle_label_get(Ecore_Config_Server *
+                                                      srv, const long);
+int                 _ecore_config_ipc_bundle_label_set(Ecore_Config_Server *
+                                                      srv, const long,
+                                                      const char *);
+long                _ecore_config_ipc_bundle_label_find(Ecore_Config_Server *
+                                                       srv, const char *);
diff --git a/src/lib/ecore_config/ecore_config_ipc_ecore.c b/src/lib/ecore_config/ecore_config_ipc_ecore.c
new file mode 100644 (file)
index 0000000..a36efe3
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* by Azundris, with thanks to Corey Donohoe <atmos@atmos.org> */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#include <Ecore_Ipc.h>
+
+#include "ecore_config_ipc.h"
+#include "ecore_config_util.h"
+#include "ecore_config_private.h"
+
+#include "Ecore_Config.h"
+
+
+/*****************************************************************************/
+
+static int
+_ecore_config_ipc_ecore_string_get(char **m, char **r)
+{
+   char               *q;
+   int                 l = 0;
+
+   if (!m || !*m)
+      return ECORE_CONFIG_ERR_NODATA;
+   if (!r)
+      return ECORE_CONFIG_ERR_FAIL;
+   q = *m;
+   if (*q != 's')
+      return ECORE_CONFIG_ERR_TYPEMISMATCH;
+   q++;
+   l = (*(q++)) << 8;
+   l += *(q++);
+   *r = q;
+   q += l;
+   *m = q;
+   WRN("IPC/eCore: got string-%d \"%s\"", l, *r);
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+static char               *
+_ecore_config_ipc_global_prop_list(Ecore_Config_Server * srv __UNUSED__, long serial __UNUSED__)
+{
+   Ecore_Config_DB_File  *db;
+   char                 **keys;
+   int                    key_count, x;
+   estring               *s;
+   int                    f;
+   char                   buf[PATH_MAX], *p;   
+   // char             *data;                  UNUSED
+   Ecore_Config_Type      type;
+
+   db = NULL;
+   s = estring_new(8192);
+   f = 0;
+   if ((p = getenv("HOME")))
+     {
+       snprintf(buf, sizeof(buf), "%s/.e/config.eet", p);
+       if (!(db = _ecore_config_db_open_read(buf)))
+         {
+            strcpy(buf, PACKAGE_DATA_DIR"/system.eet");
+            if (!(db = _ecore_config_db_open_read(buf)))
+              return NULL;
+         }
+     }
+   if (!db) return NULL;
+   key_count = 0;
+   keys = _ecore_config_db_keys_get(db, &key_count);
+   if (keys)
+     {
+       for (x = 0; x < key_count; x++)
+         {
+            type = _ecore_config_db_key_type_get(db, keys[x]);
+            switch (type)
+              {
+                 case ECORE_CONFIG_INT:
+                   estring_appendf(s, "%s%s: integer", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_BLN:
+                   estring_appendf(s, "%s%s: boolean", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_FLT:
+                   estring_appendf(s, "%s%s: float", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_STR:
+                   estring_appendf(s, "%s%s: string", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_RGB:
+                   estring_appendf(s, "%s%s: colour", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_THM:
+                   estring_appendf(s, "%s%s: theme", f ? "\n" : "", keys[x]);
+                   break;
+                 case ECORE_CONFIG_SCT:
+                   estring_appendf(s, "%s%s: structure", f ? "\n" : "", keys[x]);
+                   break;
+                 default:
+                   estring_appendf(s, "%s%s: unknown", f ? "\n" : "", keys[x]);
+                   continue;
+              }
+            f = 1;
+         }
+     }
+   _ecore_config_db_close(db);
+   if (keys)
+     {
+       for (x = 0; x < key_count; x++)
+         {
+            free(keys[x]);
+         }
+       free(keys);
+     }
+   
+   return estring_disown(s);
+}
+
+/*****************************************************************************/
+
+static int
+_ecore_config_ipc_ecore_send(Ecore_Ipc_Event_Client_Data * e, int code,
+                            char *reply)
+{
+   static int          our_ref = 0;
+   int                 len = reply ? strlen(reply) + 1 : 0;
+
+   our_ref++;
+   WRN("IPC/eCore: replying [0,0] %d IRT %d => %d {\"%s\":%d}", our_ref,
+     e->ref, code, reply ? reply : "", len);
+   return ecore_ipc_client_send(e->client, 0, 0, our_ref, e->ref, code, reply,
+                               len);
+}
+
+/*****************************************************************************/
+
+static int
+_ecore_config_ipc_ecore_handle_request(Ecore_Ipc_Server * server,
+                                      Ecore_Ipc_Event_Client_Data * e)
+{
+   Ecore_Config_Server *srv;
+   long                serial;
+   int                 ret;
+   char               *r, *k, *v, *m;
+
+   srv = _ecore_config_server_convert(server);
+   serial = e->minor;
+   r = NULL;
+   m = (char *)e->data;
+   INF("IPC/eCore: client sent: [%d,%d] #%d (%d) @ %p", e->major, e->minor,
+     e->ref, e->size, server);
+
+   switch (e->major)
+     {
+     case IPC_PROP_LIST:
+       if (srv == __ecore_config_server_global)
+          r = _ecore_config_ipc_global_prop_list(srv, serial);
+       else
+          r = _ecore_config_ipc_prop_list(srv, serial);
+       break;
+     case IPC_PROP_DESC:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+          r = _ecore_config_ipc_prop_desc(srv, serial, k);
+       break;
+     case IPC_PROP_GET:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+          r = _ecore_config_ipc_prop_get(srv, serial, k);
+       break;
+     case IPC_PROP_SET:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+         {
+            if (_ecore_config_ipc_ecore_string_get(&m, &v) ==
+                ECORE_CONFIG_ERR_SUCC)
+               return _ecore_config_ipc_ecore_send(e,
+                                                   _ecore_config_ipc_prop_set
+                                                   (srv, serial, k, v), NULL);
+         }
+       break;
+
+     case IPC_BUNDLE_LIST:
+       r = _ecore_config_ipc_bundle_list(srv);
+       break;
+     case IPC_BUNDLE_NEW:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+          return _ecore_config_ipc_ecore_send(e,
+                                              k ?
+                                              _ecore_config_ipc_bundle_new(srv,
+                                                                           k) :
+                                              ECORE_CONFIG_ERR_FAIL, NULL);
+       break;
+     case IPC_BUNDLE_LABEL_SET:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+          return _ecore_config_ipc_ecore_send(e,
+                                              k ?
+                                              _ecore_config_ipc_bundle_label_set
+                                              (srv, serial,
+                                               k) : ECORE_CONFIG_ERR_FAIL,
+                                              NULL);
+       break;
+     case IPC_BUNDLE_LABEL_FIND:
+       if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC)
+          return _ecore_config_ipc_ecore_send(e,
+                                              _ecore_config_ipc_bundle_label_find
+                                              (srv, k), NULL);
+       break;
+     case IPC_BUNDLE_LABEL_GET:
+       r = _ecore_config_ipc_bundle_label_get(srv, serial);
+       break;
+     }
+
+   ret =
+      _ecore_config_ipc_ecore_send(e,
+                                  r ? ECORE_CONFIG_ERR_SUCC :
+                                  ECORE_CONFIG_ERR_FAIL, r);
+   if (r)
+     {
+       free(r);
+       return ret;
+     }
+   return ECORE_CONFIG_ERR_NOTFOUND;
+}
+
+/*****************************************************************************/
+
+static int
+_ecore_config_ipc_client_add(void *data, int type __UNUSED__, void *event)
+{
+   Ecore_Ipc_Server  **server;
+   Ecore_Ipc_Event_Client_Data *e;
+
+   server = (Ecore_Ipc_Server **) data;
+   e = (Ecore_Ipc_Event_Client_Data *) event;
+
+   if (*server != ecore_ipc_client_server_get(e->client))
+      return 1;
+
+   INF("IPC/eCore: Client connected. @ %p", server);
+   return 1;
+}
+
+static int
+_ecore_config_ipc_client_del(void *data, int type __UNUSED__, void *event)
+{
+   Ecore_Ipc_Server  **server;
+   Ecore_Ipc_Event_Client_Data *e;
+
+   server = (Ecore_Ipc_Server **) data;
+   e = (Ecore_Ipc_Event_Client_Data *) event;
+
+   if (*server != ecore_ipc_client_server_get(e->client))
+      return 1;
+
+   INF("IPC/eCore: Client disconnected. @ %p", server);
+   return 1;
+}
+
+static int
+_ecore_config_ipc_client_sent(void *data, int type __UNUSED__, void *event)
+{
+   Ecore_Ipc_Server  **server;
+   Ecore_Ipc_Event_Client_Data *e;
+
+   server = (Ecore_Ipc_Server **) data;
+   e = (Ecore_Ipc_Event_Client_Data *) event;
+
+   if (*server != ecore_ipc_client_server_get(e->client))
+      return 1;
+
+   _ecore_config_ipc_ecore_handle_request(*server, e);
+   return 1;
+}
+
+/*****************************************************************************/
+
+int
+_ecore_config_ipc_ecore_init(const char *pipe_name, void **data)
+{
+   Ecore_Ipc_Server  **server;
+   struct stat         st;
+   char               *p;
+   int                 port;
+   char                socket[PATH_MAX];
+
+   server = (Ecore_Ipc_Server **) data;
+   port = 0;
+   if (!server)
+      return ECORE_CONFIG_ERR_FAIL;
+
+/*  if(*server)
+      return ECORE_CONFIG_ERR_IGNORED; */
+
+   ecore_init();
+   if (ecore_ipc_init() < 1)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   if ((p = getenv("HOME")))
+     {                         /* debug-only ### FIXME */
+       int                 stale;
+
+       stale = 1;
+       while (stale)
+         {
+            snprintf(socket, PATH_MAX, "%s/.ecore/%s/%d", p, pipe_name, port);
+
+            if (!stat(socket, &st))
+              {
+                 INF("IPC/eCore: pipe \"%s\" already exists!?", socket);
+/*      if(unlink(buf))
+       E(0,"IPC/eCore: could not remove pipe \"%s\": %d\n",buf,errno); }}*/
+                 port++;
+              }
+            else
+              {
+                 stale = 0;
+              }
+         }
+     }
+   *server = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, pipe_name, port, NULL);
+   ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD,
+                          _ecore_config_ipc_client_add, server);
+   ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL,
+                          _ecore_config_ipc_client_del, server);
+   ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA,
+                          _ecore_config_ipc_client_sent, server);
+
+   if (server)
+     {
+       INF("IPC/eCore: Server is listening on %s.", pipe_name);
+     }
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+int
+_ecore_config_ipc_ecore_exit(void **data)
+{
+   int                 ret;
+   Ecore_Ipc_Server  **server;
+
+   ret = ECORE_CONFIG_ERR_SUCC;
+   server = (Ecore_Ipc_Server **) data;
+
+   if (!server)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   if (*server)
+     {
+       ecore_ipc_server_del(*server);
+       *server = NULL;
+     }
+
+   ecore_ipc_shutdown();
+   ecore_shutdown();
+
+   return ret;
+}
+
+/*****************************************************************************/
+
+int
+_ecore_config_ipc_ecore_poll(void **data)
+{
+   Ecore_Ipc_Server  **server;
+
+   server = (Ecore_Ipc_Server **) data;
+
+   if (!server)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   ecore_main_loop_iterate();
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+/*****************************************************************************/
diff --git a/src/lib/ecore_config/ecore_config_ipc_main.c b/src/lib/ecore_config/ecore_config_ipc_main.c
new file mode 100644 (file)
index 0000000..edb7ed1
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* ############## bad */
+#define HAVE_EVAS2
+
+#include <signal.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <glob.h>
+#include <sys/param.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>            /* malloc(), free() */
+
+#include "Ecore.h"
+#include "Ecore_Config.h"
+#include "ecore_config_util.h"
+#include "ecore_config_ipc.h"
+
+#include "ecore_config_private.h"
+
+static Ecore_Config_Server *__ecore_config_servers;
+Ecore_Timer *ipc_timer = NULL;
+
+Ecore_Config_Server *
+_ecore_config_server_convert(void *srv)
+{
+   Ecore_Config_Server *srv_tmp;
+
+   srv_tmp = __ecore_config_servers;
+   while (srv_tmp)
+     {
+       if (srv_tmp->server == srv)
+         return srv_tmp;
+       srv_tmp = srv_tmp->next;
+     }
+
+   return __ecore_config_server_global;
+}
+
+/*****************************************************************************/
+/* INTERFACE FOR IPC MODULES */
+/*****************************/
+
+char               *
+_ecore_config_ipc_prop_list(Ecore_Config_Server * srv, const long serial)
+{
+   Ecore_Config_Bundle *theme;
+   Ecore_Config_Prop  *e;
+   estring            *s;
+   int                 f;
+
+   theme = ecore_config_bundle_by_serial_get(srv, serial);
+   e = theme ? theme->data : NULL;
+   s = estring_new(8192);
+   f = 0;
+   while (e)
+     {
+       /* ignore system properties in listings, unless they have been overridden */
+       if (e->flags & ECORE_CONFIG_FLAG_SYSTEM && !(e->flags & ECORE_CONFIG_FLAG_MODIFIED))
+         {
+            e = e->next;
+            continue;
+         }
+       estring_appendf(s, "%s%s: %s", f ? "\n" : "", e->key,
+                       ecore_config_type_get(e));
+       if (e->flags & ECORE_CONFIG_FLAG_BOUNDS)
+         {
+            if (e->type == ECORE_CONFIG_FLT)
+               estring_appendf(s, ", range %le..%le",
+                               (float)e->lo / ECORE_CONFIG_FLOAT_PRECISION,
+                               (float)e->hi / ECORE_CONFIG_FLOAT_PRECISION);
+            else
+               estring_appendf(s, ", range %d..%d", e->lo, e->hi);
+         }
+       if (e->type == ECORE_CONFIG_THM)
+          estring_appendf(s, ", group %s", e->data ? e->data : "Main");
+       f = 1;
+       e = e->next;
+     }
+
+   return estring_disown(s);
+}
+
+char               *
+_ecore_config_ipc_prop_desc(Ecore_Config_Server * srv, const long serial,
+                           const char *key)
+{
+#ifdef HAVE_EVAS2
+   Ecore_Config_Prop  *e;
+
+   e = ecore_config_get(key);
+   if (e)
+     {
+       estring            *s = estring_new(512);
+
+       estring_appendf(s, "%s: %s", e->key, ecore_config_type_get(e));
+       if (e->flags & ECORE_CONFIG_FLAG_BOUNDS)
+          estring_appendf(s, ", range %d..%d", e->lo, e->hi);
+       return estring_disown(s);
+     }
+#endif
+   return strdup("<undefined>");
+}
+
+char               *
+_ecore_config_ipc_prop_get(Ecore_Config_Server * srv, const long serial,
+                          const char *key)
+{
+#ifdef HAVE_EVAS2
+   char               *ret;
+
+   if ((ret = ecore_config_as_string_get(key)))
+      return ret;
+#endif
+   return strdup("<undefined>");
+}
+
+int
+_ecore_config_ipc_prop_set(Ecore_Config_Server * srv, const long serial,
+                          const char *key, const char *val)
+{
+#ifdef HAVE_EVAS2
+   int                 ret;
+   Ecore_Config_Bundle *theme;
+
+   theme = ecore_config_bundle_by_serial_get(srv, serial);
+   ret = ecore_config_set(key, (char *)val);
+   ERR("ipc.prop.set(%s->%s,\"%s\") => %d\n", theme ? theme->identifier : "",
+       key, val, ret);
+   return ret;
+#else
+   return ECORE_CONFIG_ERR_NOTSUPP;
+#endif
+}
+
+/*****************************************************************************/
+
+char               *
+_ecore_config_ipc_bundle_list(Ecore_Config_Server * srv)
+{
+   Ecore_Config_Bundle *ns;
+   estring            *s;
+   int                 f;
+
+   ns = ecore_config_bundle_1st_get(srv);
+   s = estring_new(8192);
+   f = 0;
+   if (!ns)
+      return strdup("<no_bundles_created>");
+
+   while (ns)
+     {
+       estring_appendf(s, "%s%d: %s", f ? "\n" : "",
+                       ecore_config_bundle_serial_get(ns),
+                       ecore_config_bundle_label_get(ns));
+       f = 1;
+       ns = ecore_config_bundle_next_get(ns);
+     }
+
+   return estring_disown(s);
+}
+
+int
+_ecore_config_ipc_bundle_new(Ecore_Config_Server * srv, const char *label)
+{
+   if (ecore_config_bundle_new(srv, label))
+      return ECORE_CONFIG_ERR_SUCC;
+   return ECORE_CONFIG_ERR_FAIL;
+}
+
+char               *
+_ecore_config_ipc_bundle_label_get(Ecore_Config_Server * srv, const long serial)
+{
+   Ecore_Config_Bundle *ns;
+   char               *label;
+
+   ns = ecore_config_bundle_by_serial_get(srv, serial);
+   label = ecore_config_bundle_label_get(ns);
+   return strdup(label ? label : "<no such bundle>");
+}
+
+int
+_ecore_config_ipc_bundle_label_set(Ecore_Config_Server * srv, const long serial,
+                                  const char *label)
+{
+   Ecore_Config_Bundle *ns;
+
+   ns = ecore_config_bundle_by_serial_get(srv, serial);
+   if (!(ns->identifier = malloc(sizeof(label))))
+      return ECORE_CONFIG_ERR_OOM;
+   memcpy(ns->identifier, label, sizeof(label));
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+long
+_ecore_config_ipc_bundle_label_find(Ecore_Config_Server * srv,
+                                   const char *label)
+{
+   Ecore_Config_Bundle *ns;
+
+   ns = ecore_config_bundle_by_label_get(srv, label);
+   return ns ? ecore_config_bundle_serial_get(ns) : -1;
+}
+
+static int
+_ecore_config_ipc_poll(void *data __UNUSED__)
+{
+   Ecore_Config_Server *s;
+
+   s = __ecore_config_servers;
+   while (s)
+     {
+       _ecore_config_ipc_ecore_poll(&s->server);
+        s = s->next;
+     }
+
+   return 1;
+}
+
+int
+_ecore_config_ipc_exit(void)
+{
+   Ecore_Config_Server *l;
+
+   if (ipc_timer)
+      ecore_timer_del(ipc_timer);
+
+   l = __ecore_config_servers;
+   while (l)
+     {
+       _ecore_config_ipc_ecore_exit(&l->server);
+        if (l->name)
+          free(l->name);
+       l = l->next;
+     }
+
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+Ecore_Config_Server *
+_ecore_config_ipc_init(const char *pipe_name)
+{
+   int                 ret;
+   Ecore_Config_Server *list;
+   Ecore_Config_Server *ret_srv;
+
+   list = NULL;
+   ret_srv = NULL;
+   list = NULL;
+
+   list = malloc(sizeof(Ecore_Config_Server));
+   memset(list, 0, sizeof(Ecore_Config_Server));
+   if ((ret = _ecore_config_ipc_ecore_init(pipe_name, &list->server)) != ECORE_CONFIG_ERR_SUCC)
+     {
+       ERR("_ecore_config_ipc_init: failed to register %s, code %d",
+         pipe_name, ret);
+     }
+
+   ERR("_ecore_config_ipc_init: registered \"%s\"...", pipe_name);
+
+   list->name = strdup(pipe_name);
+   list->next = __ecore_config_servers;
+
+   __ecore_config_servers = list;
+   if (!ret_srv)
+     ret_srv = list;
+
+   if (!ipc_timer)
+     ipc_timer = ecore_timer_add(100, _ecore_config_ipc_poll, NULL);
+   
+   return ret_srv;
+}
+/*****************************************************************************/
diff --git a/src/lib/ecore_config/ecore_config_private.h b/src/lib/ecore_config/ecore_config_private.h
new file mode 100644 (file)
index 0000000..b97f695
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _ECORE_CONFIG_PRIVATE_H
+# define _ECORE_CONFIG_PRIVATE_H
+#ifdef ECORE_CONFIG_DEFAULT_LOG_COLOR
+# undef ECORE_CONFIG_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_CONFIG_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+ /* eina_log related things */
+extern int _ecore_config_log_dom;
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_config_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_config_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_config_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_config_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_config_log_dom, __VA_ARGS__)
+/* debug */
+extern int               DEBUG;
+
+typedef struct _Ecore_Config_DB_File Ecore_Config_DB_File;
+
+int                   _ecore_config_mod_init(const char *pipe_name, void **data);
+int                   _ecore_config_mod_exit(void **data);
+int                   _ecore_config_mod_poll(void **data);
+
+Ecore_Config_DB_File *_ecore_config_db_open_read(const char *file);
+Ecore_Config_DB_File *_ecore_config_db_open_write(const char *file);
+void                  _ecore_config_db_close(Ecore_Config_DB_File *db);
+char                **_ecore_config_db_keys_get(Ecore_Config_DB_File *db, int *num_ret);
+Ecore_Config_Type     _ecore_config_db_key_type_get(Ecore_Config_DB_File *db, const char *key);
+int                   _ecore_config_db_read(Ecore_Config_DB_File *db, const char *key);
+void                  _ecore_config_db_write(Ecore_Config_DB_File *db, Ecore_Config_Prop *e);
+
+int                   _ecore_config_boolean_get(Ecore_Config_Prop *e);
+char                 *_ecore_config_string_get(Ecore_Config_Prop *e);
+long                  _ecore_config_int_get(Ecore_Config_Prop *e);
+int                   _ecore_config_argb_get(Ecore_Config_Prop *e, int *a, int *r,
+                                         int *g, int *b);
+char                 *_ecore_config_argbstr_get(Ecore_Config_Prop *e);
+long                  _ecore_config_argbint_get(Ecore_Config_Prop *e);
+float                 _ecore_config_float_get(Ecore_Config_Prop *e);
+char                 *_ecore_config_theme_get(Ecore_Config_Prop *e);
+
+int                   _ecore_config_ipc_ecore_init(const char *pipe_name, void **data);
+int                   _ecore_config_ipc_ecore_exit(void **data);
+int                   _ecore_config_ipc_ecore_poll(void **data);
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#endif
diff --git a/src/lib/ecore_config/ecore_config_storage.c b/src/lib/ecore_config/ecore_config_storage.c
new file mode 100644 (file)
index 0000000..e2c54df
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "Ecore_Config.h"
+#include "ecore_config_private.h"
+
+/**
+ * Loads the default configuration.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
+ *          is returned if the file cannot be loaded.
+ * @ingroup Ecore_Config_File_Group
+ */
+EAPI int
+ecore_config_load(void)
+{
+   char                file[PATH_MAX];
+
+   if (!__ecore_config_app_name)
+     return ECORE_CONFIG_ERR_FAIL;
+
+   snprintf(file, PATH_MAX, "%s/.e/apps/%s/config.eet", getenv("HOME"),
+           __ecore_config_app_name);
+   return ecore_config_file_load(file);
+}
+
+/**
+ * Saves the current configuration to the default file.
+ * @return  @c ECORE_CONFIG_ERR_SUCC is returned on success.
+ *          @c ECORE_CONFIG_ERR_FAIL is returned if the data cannot be
+ *          saved.
+ * @ingroup Ecore_Config_File_Group
+ */
+EAPI int
+ecore_config_save(void)
+{
+   char                file[PATH_MAX];
+
+   if (!__ecore_config_app_name)
+     return ECORE_CONFIG_ERR_FAIL;
+
+   snprintf(file, PATH_MAX, "%s/.e/apps/%s/config.eet", getenv("HOME"),
+           __ecore_config_app_name);
+   return ecore_config_file_save(file);
+}
+
+/**
+ * Load the given configuration file to the local configuration.
+ * @param   file Name of the file to load.
+ * @return  @c ECORE_CONFIG_ERR_SUCC on success.  @c ECORE_CONFIG_ERR_NODATA
+ *          is returned if the file cannot be loaded.
+ * @ingroup Ecore_Config_File_Group
+ */
+EAPI int
+ecore_config_file_load(const char *file)
+{
+   Ecore_Config_DB_File  *db;
+   char                 **keys;
+   int                    key_count;
+   int                    x;
+   // double                 ftmp;     UNUSED
+   // int                    pt;       UNUSED
+   // int                    itmp;     UNUSED
+   // Ecore_Config_Type      type;     UNUSED
+   char                   *data;
+
+   db = NULL;
+   data = NULL;
+
+   db = _ecore_config_db_open_read(file);
+   if (!db)
+     {
+       ERR("Cannot open database from file %s!", file);
+       return ECORE_CONFIG_ERR_NODATA;
+     }
+   key_count = 0;   
+   keys = _ecore_config_db_keys_get(db, &key_count);
+   if (keys)
+     {
+       for (x = 0; x < key_count; x++)
+         {
+           _ecore_config_db_read(db, keys[x]);
+         }
+     }
+   _ecore_config_db_close(db);
+   if (keys)
+     {
+       for (x = 0; x < key_count; x++)
+         {
+            free(keys[x]);
+         }
+       free(keys);
+     }
+   return ECORE_CONFIG_ERR_SUCC;
+}
+
+static void
+_ecore_config_recurse_mkdir(const char *file)
+{
+   char               *file_ptr;
+   char               *file_tmp;
+   struct stat         status;
+
+   file_tmp = strdup(file);
+   file_ptr = file_tmp + strlen(file_tmp);
+   while (*file_ptr != '/' && file_ptr > file_tmp)
+      file_ptr--;
+   *file_ptr = '\0';
+
+   if ((file_tmp[0] != 0) && stat(file_tmp, &status))
+     {
+       _ecore_config_recurse_mkdir(file_tmp);
+       mkdir(file_tmp, S_IRUSR | S_IWUSR | S_IXUSR);
+     }
+   free(file_tmp);
+}
+
+/**
+ * Saves the local configuration to the given file.
+ * @param   file Name of the file to save to.
+ * @return  @c ECORE_CONFIG_ERR_SUCC is returned on success.
+ *          @c ECORE_CONFIG_ERR_FAIL is returned if the data cannot be
+ *          saved.
+ * @ingroup Ecore_Config_File_Group
+ */
+EAPI int
+ecore_config_file_save(const char *file)
+{
+   Ecore_Config_Prop    *next;
+   Ecore_Config_DB_File *db;
+   struct stat           status;
+
+   next = __ecore_config_bundle_local->data;
+   db = NULL;
+
+   /* if file does not exist check to see if the dirs exist, creating if not */
+   if (stat(file, &status))
+      _ecore_config_recurse_mkdir(file);
+
+   db = _ecore_config_db_open_write(file);
+   if (!db)
+     {
+       ERR("Cannot open database from file %s!", file);
+       return ECORE_CONFIG_ERR_FAIL;
+     }
+
+   while (next)
+     {
+       /* let the config_db deal with this
+        * handyande: hmm, not sure that it ever does - reinstating until
+        * further discussions satisfy me!
+        */
+       if (!(next->flags & ECORE_CONFIG_FLAG_MODIFIED) || next->flags & ECORE_CONFIG_FLAG_CMDLN)
+         {
+            next = next->next;
+            continue;
+         }
+
+       _ecore_config_db_write(db, next);
+
+       next = next->next;
+     }
+
+   _ecore_config_db_close(db);
+   return ECORE_CONFIG_ERR_SUCC;
+}
diff --git a/src/lib/ecore_config/ecore_config_util.c b/src/lib/ecore_config/ecore_config_util.c
new file mode 100644 (file)
index 0000000..4f1658c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* azundris */
+
+#include <sys/types.h>
+#include <stdlib.h>            /* malloc(), free() */
+#include <stdio.h>
+#include <string.h>            /* str...() */
+
+#include <stdarg.h>            /* varargs in sprintf/appendf */
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#include "Ecore_Config.h"
+#include "ecore_config_util.h"
+
+#include "ecore_config_private.h"
+
+#define CHUNKLEN 4096
+
+/*****************************************************************************/
+/* STRINGS */
+/***********/
+
+estring            *
+estring_new(int size)
+{
+   estring            *e = malloc(sizeof(estring));
+
+   if (e)
+     {
+       memset(e, 0, sizeof(estring));
+       if ((size > 0) && (e->str = malloc(size)))
+          e->alloc = size;
+     }
+   return e;
+}
+
+char               *
+estring_disown(estring * e)
+{
+   if (e)
+     {
+       char               *r = e->str;
+
+       free(e);
+       return r;
+     }
+   return NULL;
+}
+
+int
+estring_appendf(estring * e, const char *fmt, ...)
+{
+   int      need;
+   va_list  ap;
+   char    *p;
+
+   if (!e)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   if (!e->str)
+     {
+       e->used = e->alloc = 0;
+       if (!(e->str = (char *)malloc(e->alloc = CHUNKLEN)))
+          return ECORE_CONFIG_ERR_OOM;
+     }
+
+   va_start(ap, fmt);
+   need = vsnprintf(NULL, 0, fmt, ap);
+   va_end(ap);
+
+   if (need >= (e->alloc - e->used))
+     {
+       e->alloc = e->used + need + (CHUNKLEN - (need % CHUNKLEN));
+
+       if (!(p = (char *)realloc(e->str, e->alloc)))
+          {
+            free(e->str);
+            e->alloc = e->used = 0;
+            return ECORE_CONFIG_ERR_OOM;
+          }
+       e->str = p;
+     }
+
+   va_start(ap, fmt);
+   need = vsnprintf(e->str + e->used, e->alloc - e->used, fmt, ap);
+   va_end(ap);
+
+   return e->used += need;
+}
+
+int
+esprintf(char **result, const char *fmt, ...)
+{
+   va_list   ap;
+   size_t    need;
+   char     *n;
+
+   if (!result)
+      return ECORE_CONFIG_ERR_FAIL;
+
+   va_start(ap, fmt);
+   need = vsnprintf(NULL, 0, fmt, ap) + 1;
+   va_end(ap);
+   n = malloc(need + 1);
+
+   if (n)
+     {
+       va_start(ap, fmt);
+       need = vsnprintf(n, need, fmt, ap);
+       va_end(ap);
+
+       n[need] = 0;
+
+       if(*result)
+          free(result);
+       *result = n;
+
+       return need;
+     }
+
+   return ECORE_CONFIG_ERR_OOM;
+}
+
+/*****************************************************************************/
diff --git a/src/lib/ecore_config/ecore_config_util.h b/src/lib/ecore_config/ecore_config_util.h
new file mode 100644 (file)
index 0000000..5bee9d6
--- /dev/null
@@ -0,0 +1,14 @@
+#define TIMER_STOP 0
+#define TIMER_CONT 1
+
+typedef struct _estring
+{
+   char               *str;
+   int                 alloc, used;
+} estring;
+
+estring            *estring_new(int size);
+char               *estring_disown(estring * e);
+int                 estring_appendf(estring * e, const char *fmt, ...);
+
+int                 esprintf(char **result, const char *fmt, ...);
diff --git a/src/lib/ecore_directfb/.cvsignore b/src/lib/ecore_directfb/.cvsignore
new file mode 100644 (file)
index 0000000..ce9e988
--- /dev/null
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.libs
+.deps
+*.lo
+libecore_directfb.la
diff --git a/src/lib/ecore_directfb/Ecore_DirectFB.h b/src/lib/ecore_directfb/Ecore_DirectFB.h
new file mode 100644 (file)
index 0000000..abb2ee8
--- /dev/null
@@ -0,0 +1,191 @@
+#ifndef _ECORE_DIRECTFB_H
+#define _ECORE_DIRECTFB_H
+
+#include <directfb.h>
+
+#ifdef EAPI
+#undef EAPI
+#endif
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EAPI extern int ECORE_DIRECTFB_EVENT_POSITION;
+EAPI extern int ECORE_DIRECTFB_EVENT_SIZE;
+EAPI extern int ECORE_DIRECTFB_EVENT_CLOSE;
+EAPI extern int ECORE_DIRECTFB_EVENT_DESTROYED;
+EAPI extern int ECORE_DIRECTFB_EVENT_GOT_FOCUS;
+EAPI extern int ECORE_DIRECTFB_EVENT_LOST_FOCUS;
+EAPI extern int ECORE_DIRECTFB_EVENT_KEY_DOWN;
+EAPI extern int ECORE_DIRECTFB_EVENT_KEY_UP;
+EAPI extern int ECORE_DIRECTFB_EVENT_BUTTON_DOWN;
+EAPI extern int ECORE_DIRECTFB_EVENT_BUTTON_UP;
+EAPI extern int ECORE_DIRECTFB_EVENT_MOTION;
+EAPI extern int ECORE_DIRECTFB_EVENT_ENTER;
+EAPI extern int ECORE_DIRECTFB_EVENT_LEAVE;
+EAPI extern int ECORE_DIRECTFB_EVENT_WHEEL;
+
+       
+
+#ifndef _ECORE_DIRECTFB_WINDOW_PREDEF
+typedef struct _Ecore_DirectFB_Window                  Ecore_DirectFB_Window;
+#endif
+typedef struct _Ecore_DirectFB_Cursor                  Ecore_DirectFB_Cursor;
+
+typedef struct _Ecore_DirectFB_Event_Key_Down          Ecore_DirectFB_Event_Key_Down; 
+typedef struct _Ecore_DirectFB_Event_Key_Up            Ecore_DirectFB_Event_Key_Up;
+typedef struct _Ecore_DirectFB_Event_Button_Down       Ecore_DirectFB_Event_Button_Down;
+typedef struct _Ecore_DirectFB_Event_Button_Up         Ecore_DirectFB_Event_Button_Up;
+typedef struct _Ecore_DirectFB_Event_Motion            Ecore_DirectFB_Event_Motion;
+typedef struct _Ecore_DirectFB_Event_Enter             Ecore_DirectFB_Event_Enter;
+typedef struct _Ecore_DirectFB_Event_Leave             Ecore_DirectFB_Event_Leave;
+typedef struct _Ecore_DirectFB_Event_Wheel             Ecore_DirectFB_Event_Wheel;
+typedef struct _Ecore_DirectFB_Event_Got_Focus         Ecore_DirectFB_Event_Got_Focus;
+typedef struct _Ecore_DirectFB_Event_Lost_Focus                Ecore_DirectFB_Event_Lost_Focus;
+
+
+/* this struct is to keep windows data (id, window itself and surface) in memory as every call
+ * to DirectFB for this values (e.g window->GetSurface(window,&surface)) will increment the
+ * reference count, then we will have to release N times the data, so better we just ask for 
+ them once */
+struct _Ecore_DirectFB_Window
+{
+       DFBWindowID             id;
+       IDirectFBWindow         *window;
+       IDirectFBSurface        *surface;
+       Ecore_DirectFB_Cursor   *cursor;
+       
+};
+
+struct _Ecore_DirectFB_Cursor
+{
+       IDirectFBSurface        *surface;
+       int                     hot_x;
+       int                     hot_y;
+
+};
+
+struct _Ecore_DirectFB_Event_Key_Down /** DirectFB Key Down event */
+{
+       char   *name; /**< The name of the key that was released */
+       char   *string; /**< The logical symbol of the key that was pressed */
+       char   *key_compose; /**< The UTF-8 string conversion if any */
+       unsigned int time;
+       DFBWindowID win;
+};
+   
+struct _Ecore_DirectFB_Event_Key_Up /** DirectFB Key Up event */
+{
+       char   *name; /**< The name of the key that was released */
+       char   *string; /**< The logical symbol of the key that was pressed */
+       char   *key_compose; /**< The UTF-8 string conversion if any */
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Button_Down
+{
+       int button;
+       int modifiers;
+       int x, y;
+       unsigned int time;
+       int double_click : 1;
+       int triple_click : 1;
+       DFBWindowID win;
+};
+struct _Ecore_DirectFB_Event_Button_Up
+{
+       int button;
+       int modifiers;
+       int x, y;
+       unsigned int time;
+       DFBWindowID win;
+};
+struct _Ecore_DirectFB_Event_Motion
+{
+       int modifiers;
+       int x, y;
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Enter
+{
+       int modifiers;
+       int x, y;
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Leave
+{
+       int modifiers;
+       int x, y;
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Wheel
+{
+       int direction;
+       int z;
+       int modifiers;
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Got_Focus
+{
+       unsigned int time;
+       DFBWindowID win;
+};
+
+struct _Ecore_DirectFB_Event_Lost_Focus
+{
+       unsigned int time;
+       DFBWindowID win;
+};
+
+/* main functions */
+EAPI int ecore_directfb_init(const char *name);
+EAPI int ecore_directfb_shutdown(void);
+EAPI IDirectFB * ecore_directfb_interface_get(void);
+/* window operations */
+EAPI Ecore_DirectFB_Window * ecore_directfb_window_new(int x, int y, int w, int h);
+EAPI void ecore_directfb_window_free(Ecore_DirectFB_Window *window);
+EAPI void ecore_directfb_window_move(Ecore_DirectFB_Window *window, int x, int y);
+EAPI void ecore_directfb_window_resize(Ecore_DirectFB_Window *window, int w, int h);
+EAPI void ecore_directfb_window_focus(Ecore_DirectFB_Window *window);
+EAPI void ecore_directfb_window_show(Ecore_DirectFB_Window *window);
+EAPI void ecore_directfb_window_hide(Ecore_DirectFB_Window *window);
+EAPI void ecore_directfb_window_shaped_set(Ecore_DirectFB_Window *window, int set);
+EAPI void ecore_directfb_window_fullscreen_set(Ecore_DirectFB_Window *window, int set);
+EAPI void ecore_directfb_window_size_get(Ecore_DirectFB_Window *window, int *w, int *h);
+EAPI void ecore_directfb_window_cursor_show(Ecore_DirectFB_Window *window, int show);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_directfb/Makefile.am b/src/lib/ecore_directfb/Makefile.am
new file mode 100644 (file)
index 0000000..d270ae2
--- /dev/null
@@ -0,0 +1,35 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore \
+@DIRECTFB_CFLAGS@ @EINA_CFLAGS@
+
+if BUILD_ECORE_DIRECTFB
+
+lib_LTLIBRARIES = libecore_directfb.la
+include_HEADERS = \
+Ecore_DirectFB.h
+
+libecore_directfb_la_SOURCES = \
+ecore_directfb.c \
+ecore_directfb_keys.h \
+ecore_directfb_private.h
+
+libecore_directfb_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@DIRECTFB_LIBS@ \
+@EINA_LIBS@
+
+libecore_directfb_la_LDFLAGS = -version-info @version_info@ @ecore_directfb_release_info@
+
+libecore_directfb_la_DEPENDENCIES = \
+$(top_builddir)/src/lib/ecore/libecore.la
+
+endif
+
+EXTRA_DIST = \
+Ecore_DirectFB.h \
+ecore_directfb.c \
+ecore_directfb_keys.h \
+ecore_directfb_private.h
diff --git a/src/lib/ecore_directfb/ecore_directfb.c b/src/lib/ecore_directfb/ecore_directfb.c
new file mode 100644 (file)
index 0000000..2b6c44d
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "Ecore_DirectFB.h"
+#include "ecore_directfb_private.h"
+#include "ecore_directfb_keys.h"
+#include "Ecore.h"
+#include "ecore_private.h"
+
+/* ecore_directfb */
+/******************/
+/* About */
+/* with this you can create windows of directfb and handle events through ecore
+ * TODO:
+ * - handle all event types
+ * - 
+ * */
+int _ecore_directfb_log_dom = -1;
+
+
+static int _ecore_directfb_init_count = 0;
+
+static int _window_event_fd = 0;
+static int _input_event_fd = 0;
+
+static int _ecore_directfb_fullscreen_window_id = 0;
+static int _cursor_x = 0;
+static int _cursor_y = 0;
+
+EAPI int ECORE_DIRECTFB_EVENT_POSITION = 0;
+EAPI int ECORE_DIRECTFB_EVENT_SIZE = 0;
+EAPI int ECORE_DIRECTFB_EVENT_CLOSE = 0;
+EAPI int ECORE_DIRECTFB_EVENT_DESTROYED = 0;
+EAPI int ECORE_DIRECTFB_EVENT_GOT_FOCUS = 0;
+EAPI int ECORE_DIRECTFB_EVENT_LOST_FOCUS = 0;
+EAPI int ECORE_DIRECTFB_EVENT_KEY_DOWN = 0;
+EAPI int ECORE_DIRECTFB_EVENT_KEY_UP = 0;
+EAPI int ECORE_DIRECTFB_EVENT_BUTTON_DOWN = 0;
+EAPI int ECORE_DIRECTFB_EVENT_BUTTON_UP = 0;
+EAPI int ECORE_DIRECTFB_EVENT_MOTION = 0;
+EAPI int ECORE_DIRECTFB_EVENT_ENTER = 0;
+EAPI int ECORE_DIRECTFB_EVENT_LEAVE = 0;
+EAPI int ECORE_DIRECTFB_EVENT_WHEEL = 0;
+
+
+static Ecore_Fd_Handler *_window_event_fd_handler_handle = NULL;
+static Ecore_Fd_Handler *_input_event_fd_handler_handle = NULL;
+
+/* this hash is to store all the possible key names for fast lookup */
+static Eina_Hash *_ecore_directfb_key_symbols_hash = NULL;
+
+
+static IDirectFB *_dfb = NULL;                 // the main interface
+static IDirectFBEventBuffer *_window_event;    // the main event buffer (all windows are attached to this)
+static IDirectFBEventBuffer *_input_event;     // the main event buffer (all windows are attached to this)
+static IDirectFBDisplayLayer *_layer;          // the main layer
+static DFBResult _err;                         // usefull for DFBCHECK
+
+
+/*******************/
+/* local functions */
+/*******************/
+
+/* free ecore directfb events functions */
+/****************************************/
+
+static void 
+_ecore_directfb_event_free_key_down(void *data __UNUSED__, void *ev)
+{
+   Ecore_DirectFB_Event_Key_Up *e;
+   
+   e = ev;
+   if(e->name) free(e->name);
+   if (e->string) free(e->string);
+   if (e->key_compose) free(e->key_compose);
+   free(e);
+}
+
+static void
+_ecore_directfb_event_free_key_up(void *data __UNUSED__, void *ev)
+{
+   Ecore_DirectFB_Event_Key_Up *e;
+   
+   e = ev;
+   if(e->name) free(e->name);
+   if (e->string) free(e->string);
+   if (e->key_compose) free(e->key_compose);
+   free(e);
+}
+
+
+/* directfb window input events handler */
+/****************************************/
+
+static void
+_ecore_directfb_event_handle_motion(DFBEvent *evt)
+{
+
+       Ecore_DirectFB_Event_Motion *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Motion));
+
+       switch(evt->clazz)
+       {
+               case DFEC_INPUT:
+                       e->modifiers = 0;
+                       switch(evt->input.axis)
+                       {
+                               case DIAI_X:
+                                       e->x = _cursor_x = evt->input.axisabs;
+                                       e->y = _cursor_y;
+                                       break;
+                               case DIAI_Y:
+                                       e->y = _cursor_y = evt->input.axisabs;
+                                       e->x = _cursor_x;
+                                       break;
+                               case DIAI_Z:
+                                       //_ecore_directfb_event_handle_wheel(evt);
+                                       return;
+                               default:
+                                       return;
+                       }
+                       e->win = _ecore_directfb_fullscreen_window_id;
+                       e->time = 0;
+                       break;
+             
+               case DFEC_WINDOW:
+                       e->modifiers = 0;
+                       e->x = evt->window.x;
+                       e->y = evt->window.y;
+                       e->win = evt->window.window_id;
+                       e->time = 0;
+                       break;
+               default:
+                       break;
+       }
+       ecore_event_add(ECORE_DIRECTFB_EVENT_MOTION, e, NULL, NULL);
+}
+static void
+_ecore_directfb_event_handle_key_down(DFBEvent *evt)
+{
+
+       Ecore_DirectFB_Event_Key_Down *e;
+       unsigned int key_symbol;
+       struct keymap *k;
+       
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Key_Down));
+       
+       switch(evt->clazz)
+       {
+               case DFEC_INPUT:
+                       key_symbol = evt->input.key_symbol;
+                       k = eina_hash_find(_ecore_directfb_key_symbols_hash, &key_symbol);
+
+                       if(!k) 
+                       {
+                               ERR("error en el numero, %0X", evt->input.key_symbol);
+                               return;
+                       }
+                       e->name = strdup(k->name);
+                       e->string = strdup(k->string);
+                       e->key_compose = NULL;
+                       e->win = _ecore_directfb_fullscreen_window_id;
+                       e->time = 0;
+                       break;
+             
+               case DFEC_WINDOW:
+                       key_symbol = evt->window.key_symbol;
+                       k = eina_hash_find(_ecore_directfb_key_symbols_hash, &key_symbol);
+
+                       if(!k) 
+                       {
+                               ERR("error en el numero, %0X", evt->window.key_symbol);
+                               return;
+                       }
+                       e->name = strdup(k->name);
+                       e->string = strdup(k->string);
+                       e->key_compose = NULL;
+                       e->win = evt->window.window_id;
+                       e->time = 0;
+                       break;
+               default:
+                       break;
+       }
+                               
+       ecore_event_add(ECORE_DIRECTFB_EVENT_KEY_DOWN, e, _ecore_directfb_event_free_key_down, NULL);
+}
+static void
+_ecore_directfb_event_handle_key_up(DFBEvent *evt)
+{
+       Ecore_DirectFB_Event_Key_Up *e;
+       unsigned int key_symbol;
+       struct keymap *k;
+       
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Key_Up));
+       
+       switch(evt->clazz)
+       {
+               case DFEC_INPUT:
+                       key_symbol = evt->input.key_symbol;
+                       k = eina_hash_find(_ecore_directfb_key_symbols_hash, &key_symbol);
+
+                       
+                       if(!k) 
+                       {
+                               ERR("error en el numero, %0X", evt->input.key_symbol);
+                               return;
+                       }
+                       e->name = strdup(k->name);
+                       e->string = strdup(k->string);
+                       e->key_compose = NULL;
+                       e->win = _ecore_directfb_fullscreen_window_id;
+                       e->time = 0;
+                       break;
+             
+               case DFEC_WINDOW:
+                       key_symbol = evt->window.key_symbol;
+                       k = eina_hash_find(_ecore_directfb_key_symbols_hash, &key_symbol);
+
+                       if(!k) 
+                       {
+                               ERR("error en el numero, %0X", evt->window.key_symbol);
+                               return;
+                       }
+                       e->name = strdup(k->name);
+                       e->string = strdup(k->string);
+                       e->key_compose = NULL;
+                       e->win = evt->window.window_id;
+                       e->time = 0;
+                       break;
+               default:
+                       break;
+       }
+       ecore_event_add(ECORE_DIRECTFB_EVENT_KEY_UP, e, _ecore_directfb_event_free_key_up, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_button_down(DFBEvent *evt)
+{
+       Ecore_DirectFB_Event_Button_Down *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Button_Down));
+
+       switch(evt->clazz)
+       {
+               case DFEC_INPUT:
+                       e->button = evt->input.button + 1;
+                       e->modifiers = 0;
+                       DFBCHECK(_layer->GetCursorPosition(_layer,&e->x,&e->y));
+                       e->x = _cursor_x;
+                       e->y = _cursor_y;
+                       e->win = _ecore_directfb_fullscreen_window_id;
+                       e->time = 0;
+                       
+                       break;
+             
+               case DFEC_WINDOW:
+                       e->button = evt->window.button + 1;
+                       e->modifiers = 0;
+                       e->x = evt->window.x;
+                       e->y = evt->window.y;
+                       e->win = evt->window.window_id;
+                       e->time = 0;
+                       break;
+               default:
+                       break;
+       }
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_BUTTON_DOWN, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_button_up(DFBEvent *evt)
+{
+       Ecore_DirectFB_Event_Button_Up *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Button_Up));
+
+       switch(evt->clazz)
+       {
+               case DFEC_INPUT:
+                       e->button = evt->input.button + 1;
+                       e->modifiers = 0;
+                       e->x = _cursor_x;
+                       e->y = _cursor_y; 
+                       e->win = _ecore_directfb_fullscreen_window_id;
+                       e->time = 0;
+                       
+                       break;
+             
+               case DFEC_WINDOW:
+                       e->button = evt->window.button + 1;
+                       e->modifiers = 0;
+                       e->x = evt->window.x;
+                       e->y = evt->window.y;
+                       e->win = evt->window.window_id;
+                       e->time = 0;
+                       break;
+               default:
+                       break;
+       }
+       ecore_event_add(ECORE_DIRECTFB_EVENT_BUTTON_UP, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_enter(DFBWindowEvent *evt)
+{
+       Ecore_DirectFB_Event_Enter *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Enter));
+
+       e->modifiers = 0;
+       e->x = evt->x;
+       e->y = evt->y;
+       e->win = evt->window_id;
+       e->time = 0;
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_ENTER, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_leave(DFBWindowEvent *evt)
+{
+       Ecore_DirectFB_Event_Leave *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Leave));
+
+       e->modifiers = 0;
+       e->x = evt->x;
+       e->y = evt->y;
+       e->win = evt->window_id;
+       e->time = 0;
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_LEAVE, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_wheel(DFBWindowEvent *evt)
+{
+       Ecore_DirectFB_Event_Wheel *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Wheel));
+
+       // currently there's no direction (only up/down);
+       e->direction = 0;
+       e->z = evt->step;
+       e->modifiers = 0;
+       e->win = evt->window_id;
+       e->time = 0;
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_WHEEL, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_got_focus(DFBWindowEvent *evt)
+{
+       Ecore_DirectFB_Event_Got_Focus *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Got_Focus));
+
+       e->win = evt->window_id;
+       e->time = 0;
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_GOT_FOCUS, e, NULL, NULL);
+
+}
+
+static void
+_ecore_directfb_event_handle_lost_focus(DFBWindowEvent *evt)
+{
+       Ecore_DirectFB_Event_Lost_Focus *e;
+       e = calloc(1, sizeof(Ecore_DirectFB_Event_Lost_Focus));
+
+       e->win = evt->window_id;
+       e->time = 0;
+                       
+       ecore_event_add(ECORE_DIRECTFB_EVENT_LOST_FOCUS, e, NULL, NULL);
+
+}
+
+
+/* inputs and windows fds handlers */
+/***********************************/
+/* TODO fix this to handle windows and input events (fullscreen/window mode)
+ * in fullscreen theres no window_id so get the id from a global var (only one fullscreen
+ * window at a time */
+
+
+static int
+_ecore_directfb_input_event_fd_handler(void *data __UNUSED__,Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+       DFBEvent evt;
+       int v = 0;
+               
+       v = read(_input_event_fd, &evt, sizeof(DFBEvent));
+       if (v < 0) return 1;
+       if (v < 1) return 1;
+       
+       /* we are getting duplicate events, only parse if we are in fullscreen */
+       //if(_ecore_directfb_fullscreen_window_id == 0) break;
+       if(evt.input.type == DIET_KEYPRESS)
+               _ecore_directfb_event_handle_key_down(&evt);
+       if(evt.input.type == DIET_KEYRELEASE)
+               _ecore_directfb_event_handle_key_up(&evt);
+       if(evt.input.type == DIET_BUTTONPRESS)
+               _ecore_directfb_event_handle_button_down(&evt);
+       if(evt.input.type == DIET_BUTTONRELEASE)
+               _ecore_directfb_event_handle_button_up(&evt);
+       if(evt.input.type == DIET_AXISMOTION)
+               _ecore_directfb_event_handle_motion(&evt);
+
+       return 1;
+}
+       
+static int
+_ecore_directfb_window_event_fd_handler(void *data __UNUSED__,Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+       DFBEvent evt;
+       int v = 0;
+               
+       v = read(_window_event_fd, &evt, sizeof(DFBEvent));
+       if (v < 0) return 1;
+       if (v < 1) return 1;
+                       
+       if(evt.window.type & DWET_POSITION)
+               INF("position");
+       if(evt.window.type & DWET_SIZE)
+               INF("size");
+       if(evt.window.type & DWET_CLOSE)
+               INF("close");
+       if(evt.window.type & DWET_DESTROYED)
+               INF("destroyed");
+       if(evt.window.type & DWET_GOTFOCUS)
+               _ecore_directfb_event_handle_got_focus(&evt.window);
+       if(evt.window.type & DWET_LOSTFOCUS)
+               _ecore_directfb_event_handle_lost_focus(&evt.window);
+       if(evt.window.type & DWET_KEYDOWN)
+               _ecore_directfb_event_handle_key_down(&evt);
+       if(evt.window.type & DWET_KEYUP)
+               _ecore_directfb_event_handle_key_up(&evt);
+       if(evt.window.type & DWET_BUTTONDOWN)
+               _ecore_directfb_event_handle_button_down(&evt);
+       if(evt.window.type & DWET_BUTTONUP)
+               _ecore_directfb_event_handle_button_up(&evt);
+       if(evt.window.type & DWET_MOTION)
+               _ecore_directfb_event_handle_motion(&evt);
+       if(evt.window.type & DWET_ENTER)
+               _ecore_directfb_event_handle_enter(&evt.window);
+       if(evt.window.type & DWET_LEAVE)
+               _ecore_directfb_event_handle_leave(&evt.window);
+       if(evt.window.type & DWET_WHEEL)
+               _ecore_directfb_event_handle_wheel(&evt.window);
+       return 1;
+}
+       
+/* api functions */
+/*****************/
+
+
+EAPI IDirectFB *
+ecore_directfb_interface_get(void)
+{
+       return _dfb;
+}
+
+
+
+EAPI Ecore_DirectFB_Window *
+ecore_directfb_window_new(int x, int y, int w, int h)
+{
+       Ecore_DirectFB_Window *window;
+       IDirectFBWindow *dfb_window;
+       IDirectFBSurface *dfb_surface = NULL;
+       DFBWindowDescription desc;
+       DFBWindowID id;
+       
+       memset(&desc, 0, sizeof(DFBWindowDescription));
+       desc.flags = (DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
+       desc.posx = x;
+       desc.posy = y;
+       desc.width = w;
+       desc.height = h;
+       desc.caps = DWCAPS_ALPHACHANNEL;
+       
+       DFBCHECK(_layer->CreateWindow(_layer, &desc, &dfb_window));
+       
+       dfb_window->AttachEventBuffer(dfb_window, _window_event);
+       dfb_window->SetOptions(dfb_window,DWOP_NONE);
+       dfb_window->SetOpacity(dfb_window, 0xFF);
+       
+       DFBCHECK(dfb_window->GetID(dfb_window, &id));
+       DFBCHECK(dfb_window->GetSurface(dfb_window,&dfb_surface));
+       
+       window = malloc(sizeof(Ecore_DirectFB_Window)); 
+       window->id = id;
+       window->window = dfb_window;
+       window->surface = dfb_surface;
+       window->cursor = NULL;
+
+       return window;
+}
+
+EAPI void
+ecore_directfb_window_free(Ecore_DirectFB_Window *ecore_window)
+{
+       DFBCHECK(ecore_window->surface->Release(ecore_window->surface));
+       DFBCHECK(ecore_window->window->Release(ecore_window->window));
+       free(ecore_window);
+}
+
+
+EAPI void
+ecore_directfb_window_move(Ecore_DirectFB_Window *ecore_window, int x, int y)
+{
+       DFBCHECK(ecore_window->window->MoveTo(ecore_window->window, x, y));
+}
+
+EAPI void
+ecore_directfb_window_resize(Ecore_DirectFB_Window *ecore_window, int w, int h)
+{
+       DFBCHECK(ecore_window->window->Resize(ecore_window->window, w, h));
+}
+
+EAPI void 
+ecore_directfb_window_focus(Ecore_DirectFB_Window *ecore_window)
+{      
+       DFBCHECK(ecore_window->window->RequestFocus(ecore_window->window));     
+}
+
+EAPI void 
+ecore_directfb_window_hide(Ecore_DirectFB_Window *ecore_window)
+{
+       DFBCHECK(ecore_window->window->SetOpacity(ecore_window->window,0));
+
+}
+
+EAPI void
+ecore_directfb_window_show(Ecore_DirectFB_Window *ecore_window)
+{
+       DFBCHECK(ecore_window->window->SetOpacity(ecore_window->window, 0xFF));
+}
+
+EAPI void
+ecore_directfb_window_shaped_set(Ecore_DirectFB_Window *ecore_window, int set)
+{
+       DFBWindowOptions opts;
+       
+       DFBCHECK(ecore_window->window->GetOptions(ecore_window->window, &opts));
+       if(set)
+       {
+               opts |= DWOP_SHAPED;
+               opts |= DWOP_ALPHACHANNEL;
+               DFBCHECK(ecore_window->window->SetOptions(ecore_window->window, opts));
+       }
+       else
+       {
+               opts &= ~DWOP_SHAPED;
+               opts &= ~DWOP_ALPHACHANNEL;
+               DFBCHECK(ecore_window->window->SetOptions(ecore_window->window, opts));
+       }
+}
+
+EAPI void
+ecore_directfb_window_cursor_show(Ecore_DirectFB_Window *ecore_window, int show)
+{
+       if(!show)
+       {
+               /* create an empty cursor and set it */
+               IDirectFBSurface *cursor;
+               DFBSurfaceDescription desc;
+                       
+               memset(&desc, 0, sizeof(DFBSurfaceDescription));
+               desc.flags = (DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PIXELFORMAT);
+               desc.width = 1;
+               desc.height = 1;
+               desc.pixelformat = DSPF_A1;
+                       
+               DFBCHECK(_dfb->CreateSurface(_dfb,&desc,&cursor));
+               DFBCHECK(cursor->Clear(cursor,0,0,0,0));
+               DFBCHECK(ecore_window->window->SetCursorShape(ecore_window->window, cursor, 0, 0));
+       }
+       else
+       {
+               /* we already have a cursor surface so set it*/
+               if(ecore_window->cursor)
+               {
+                       DFBCHECK(ecore_window->window->SetCursorShape(ecore_window->window, ecore_window->cursor->surface, ecore_window->cursor->hot_x, ecore_window->cursor->hot_y));
+               }
+               /* or just set the default directfb cursor */
+               else
+               {
+                       DFBCHECK(ecore_window->window->SetCursorShape(ecore_window->window, NULL, 0, 0));
+               }
+                       
+       }
+}
+
+EAPI void
+ecore_directfb_window_cursor_set(Ecore_DirectFB_Window *ecore_window, Ecore_DirectFB_Cursor *cursor)
+{
+       if( (!cursor) && (ecore_window->cursor))
+       {
+               ecore_window->cursor = NULL;
+               DFBCHECK(ecore_window->window->SetCursorShape(ecore_window->window, NULL, 0, 0));
+               return;
+       }
+       if(cursor)      
+       {
+               ecore_window->cursor = cursor;
+               DFBCHECK(ecore_window->window->SetCursorShape(ecore_window->window, cursor->surface, cursor->hot_x, cursor->hot_y));
+               
+       }
+
+}
+
+EAPI void 
+ecore_directfb_window_fullscreen_set(Ecore_DirectFB_Window *ecore_window, int on)
+{
+       // always release the surface (we are going to get a new one in both cases)
+       DFBCHECK(ecore_window->surface->Release(ecore_window->surface));
+       if(on)
+       {
+               DFBCHECK(_layer->SetCooperativeLevel(_layer,DLSCL_EXCLUSIVE));
+               DFBCHECK(_layer->GetSurface(_layer,&ecore_window->surface));
+               DFBCHECK(_dfb->CreateInputEventBuffer(_dfb, DICAPS_ALL, DFB_FALSE, &_input_event));
+               DFBCHECK(_input_event->CreateFileDescriptor(_input_event,&_input_event_fd));
+               /* the event of axismove sends one axis at a time, so we must store both */
+               DFBCHECK(_layer->GetCursorPosition(_layer,&_cursor_x,&_cursor_y));
+               
+               _input_event_fd_handler_handle = ecore_main_fd_handler_add(_input_event_fd,ECORE_FD_READ,_ecore_directfb_input_event_fd_handler, NULL,NULL,NULL);
+               _ecore_directfb_fullscreen_window_id = ecore_window->id;
+       }
+       else
+       {
+               DFBCHECK(_input_event->Release(_input_event));  
+               DFBCHECK(_layer->SetCooperativeLevel(_layer,DLSCL_SHARED));
+               DFBCHECK(ecore_window->window->GetSurface(ecore_window->window, &ecore_window->surface));
+               ecore_main_fd_handler_del(_input_event_fd_handler_handle);
+               _ecore_directfb_fullscreen_window_id = 0;
+       }
+               
+}
+
+EAPI void
+ecore_directfb_window_size_get(Ecore_DirectFB_Window *ecore_window, int *w, int *h)
+{
+       DFBCHECK(ecore_window->surface->GetSize(ecore_window->surface,w,h));
+       return;
+}
+
+EAPI int
+ecore_directfb_init(const char *name __UNUSED__)
+{
+       int i = 0;
+       
+       if (++_ecore_directfb_init_count != 1) return _ecore_directfb_init_count;
+       _ecore_directfb_log_dom = eina_log_domain_register("EcoreDirectFB", ECORE_DIRECTFB_DEFAULT_LOG_COLOR);
+       if(_ecore_directfb_log_dom < 0) 
+         {
+           EINA_LOG_ERR("Impossible to create a log domain for the Ecore directFB module.");
+           return _ecore_directfb_init_count--;
+         }
+       DFBCHECK(DirectFBInit(NULL,NULL));
+       DFBCHECK(DirectFBCreate(&_dfb));
+       
+       DFBCHECK(_dfb->GetDisplayLayer(_dfb, DLID_PRIMARY, &_layer));
+       DFBCHECK(_layer->SetCooperativeLevel(_layer, DLSCL_SHARED));
+       
+       
+       /* window events and fd */
+       DFBCHECK(_dfb->CreateEventBuffer(_dfb, &_window_event));
+       DFBCHECK(_window_event->CreateFileDescriptor(_window_event,&_window_event_fd));
+       _window_event_fd_handler_handle = ecore_main_fd_handler_add(_window_event_fd,ECORE_FD_READ,_ecore_directfb_window_event_fd_handler, NULL,NULL,NULL);
+       
+       /* register ecore directfb events */
+       ECORE_DIRECTFB_EVENT_POSITION   = ecore_event_type_new();
+       ECORE_DIRECTFB_EVENT_SIZE = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_CLOSE = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_DESTROYED = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_GOT_FOCUS = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_LOST_FOCUS = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_KEY_DOWN = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_KEY_UP = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_BUTTON_DOWN = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_BUTTON_UP = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_MOTION = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_ENTER = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_LEAVE = ecore_event_type_new();;
+       ECORE_DIRECTFB_EVENT_WHEEL = ecore_event_type_new();;
+
+       /* create the hash table for the keynames */
+       _ecore_directfb_key_symbols_hash = eina_hash_int32_new(free);
+       for(i=0; i<_ecore_directfb_key_symbols_count; i++)
+       {
+               struct keymap *k;
+               k = malloc(sizeof(struct keymap));
+               k->name = _ecore_directfb_key_symbols[i].name;
+               k->string = _ecore_directfb_key_symbols[i].string;
+               eina_hash_add(_ecore_directfb_key_symbols_hash, &_ecore_directfb_key_symbols[i].id, k);
+       }
+       /* create the hash for the windows(key = windowid, val = Ecore_DirectFB_Window struct) */
+       return _ecore_directfb_init_count;
+}
+
+EAPI int
+ecore_directfb_shutdown(void)
+{
+       if (--_ecore_directfb_init_count != 0) return _ecore_directfb_init_count;
+
+       ecore_main_fd_handler_del(_window_event_fd_handler_handle);
+       eina_hash_free(_ecore_directfb_key_symbols_hash);
+
+       if(_ecore_directfb_fullscreen_window_id)
+       {
+               DFBCHECK(_input_event->Release(_input_event));  
+               ecore_main_fd_handler_del(_input_event_fd_handler_handle);
+       }
+       DFBCHECK(_window_event->Release(_window_event));        
+       DFBCHECK(_layer->Release(_layer));
+       DFBCHECK(_dfb->Release(_dfb));
+       eina_log_domain_unregister(_ecore_directfb_log_dom);
+       _ecore_directfb_log_dom = -1;
+       return _ecore_directfb_init_count;
+}
diff --git a/src/lib/ecore_directfb/ecore_directfb_keys.h b/src/lib/ecore_directfb/ecore_directfb_keys.h
new file mode 100644 (file)
index 0000000..9b2c96f
--- /dev/null
@@ -0,0 +1,184 @@
+typedef struct _Ecore_DirectFB_Key_Symbols Ecore_DirectFB_Key_Symbols;
+struct _Ecore_DirectFB_Key_Symbols
+{
+       char *string;
+       char *name;
+       unsigned int id;
+};
+
+static const Ecore_DirectFB_Key_Symbols _ecore_directfb_key_symbols[] = {
+       {"\010", "BackSpace",DIKS_BACKSPACE},
+       {"\011", "Tab", DIKS_TAB},
+       {"\015", "Return", DIKS_RETURN},
+       {"", "Cancel", DIKS_CANCEL},
+       {"", "Escape", DIKS_ESCAPE},
+       {" ", "space", DIKS_SPACE},
+       {"!", "exclam", DIKS_EXCLAMATION_MARK},
+       {"\"", "quotedbl", DIKS_QUOTATION},
+       {"#", "numbersign", DIKS_NUMBER_SIGN},
+       {"$", "dollar", DIKS_DOLLAR_SIGN},
+       {"%", "percent", DIKS_PERCENT_SIGN},
+       {"&", "ampersand", DIKS_AMPERSAND},
+       {"'", "apostrophe", DIKS_APOSTROPHE},
+       {"(", "parenleft", DIKS_PARENTHESIS_LEFT},
+       {")", "parenright", DIKS_PARENTHESIS_RIGHT},
+       {"*", "asterisk", DIKS_ASTERISK},
+       {"+", "plus", DIKS_PLUS_SIGN},
+       {",", "comma", DIKS_COMMA},
+       {"-", "minus", DIKS_MINUS_SIGN},
+       {".", "period", DIKS_PERIOD},
+       {"/", "slash", DIKS_SLASH},
+       {"0", "0", DIKS_0},
+       {"1", "1", DIKS_1},
+       {"2", "2", DIKS_2},
+       {"3", "3", DIKS_3},
+       {"4", "4", DIKS_4},
+       {"5", "5", DIKS_5},
+       {"6", "6", DIKS_6},
+       {"7", "7", DIKS_7},
+       {"8", "8", DIKS_8},
+       {"9", "9", DIKS_9},
+       {":", "colon", DIKS_COLON},
+       {";", "semicolon", DIKS_SEMICOLON},
+       {"<", "less", DIKS_LESS_THAN_SIGN},
+       {"=", "equal", DIKS_EQUALS_SIGN},
+       {">", "greater", DIKS_GREATER_THAN_SIGN},
+       {"?", "question", DIKS_QUESTION_MARK},
+       {"@", "at", DIKS_AT},
+       {"A", "A", DIKS_CAPITAL_A },
+       {"B", "B", DIKS_CAPITAL_B },
+       {"C", "C", DIKS_CAPITAL_C },
+       {"D", "D", DIKS_CAPITAL_D },
+       {"E", "E", DIKS_CAPITAL_E },
+       {"F", "F", DIKS_CAPITAL_F },
+       {"G", "G", DIKS_CAPITAL_G },
+       {"H", "H", DIKS_CAPITAL_H },
+       {"I", "I", DIKS_CAPITAL_I },
+       {"J", "J", DIKS_CAPITAL_J },
+       {"K", "K", DIKS_CAPITAL_K },
+       {"L", "L", DIKS_CAPITAL_L },
+       {"M", "M", DIKS_CAPITAL_M },
+       {"N", "N", DIKS_CAPITAL_N },
+       {"O", "O", DIKS_CAPITAL_O },
+       {"P", "P", DIKS_CAPITAL_P },
+       {"Q", "Q", DIKS_CAPITAL_Q },
+       {"R", "R", DIKS_CAPITAL_R },
+       {"S", "S", DIKS_CAPITAL_S },
+       {"T", "T", DIKS_CAPITAL_T },
+       {"U", "U", DIKS_CAPITAL_U },
+       {"V", "V", DIKS_CAPITAL_V },
+       {"W", "W", DIKS_CAPITAL_W },
+       {"X", "X", DIKS_CAPITAL_X },
+       {"Y", "Y", DIKS_CAPITAL_Y },
+       {"Z", "Z", DIKS_CAPITAL_Z },
+       {"[", "bracketleft", DIKS_SQUARE_BRACKET_LEFT },
+       {"\\", "backslash", DIKS_BACKSLASH },
+       {"]", "bracketright", DIKS_SQUARE_BRACKET_RIGHT },
+       {"^", "asciicircum", DIKS_CIRCUMFLEX_ACCENT },
+       {"_", "underscore", DIKS_UNDERSCORE },
+       {"`", "grave", DIKS_GRAVE_ACCENT},
+       {"a", "a", DIKS_SMALL_A },
+       {"b","b", DIKS_SMALL_B },
+       {"c","c", DIKS_SMALL_C },
+       {"d","d", DIKS_SMALL_D },
+       {"e","e", DIKS_SMALL_E },
+       {"f","f", DIKS_SMALL_F },
+       {"g","g", DIKS_SMALL_G },
+       {"h","h", DIKS_SMALL_H },
+       {"i","i", DIKS_SMALL_I },
+       {"j","j", DIKS_SMALL_J },
+       {"k","k", DIKS_SMALL_K },
+       {"l","l", DIKS_SMALL_L },
+       {"m","m", DIKS_SMALL_M },
+       {"n","n", DIKS_SMALL_N },
+       {"o", "o", DIKS_SMALL_O },
+       {"p", "p", DIKS_SMALL_P },
+       {"q", "q", DIKS_SMALL_Q },
+       {"r", "r", DIKS_SMALL_R },
+       {"s", "s", DIKS_SMALL_S },
+       {"t", "t", DIKS_SMALL_T },
+       {"u", "u", DIKS_SMALL_U },
+       {"v", "v", DIKS_SMALL_V },
+       {"w", "w", DIKS_SMALL_W },
+       {"x", "x", DIKS_SMALL_X },
+       {"y", "y", DIKS_SMALL_Y },
+       {"z", "z", DIKS_SMALL_Z },
+       {"{", "braceleft",DIKS_CURLY_BRACKET_LEFT },
+       {"|", "bar", DIKS_VERTICAL_BAR },
+       {"}", "braceright", DIKS_CURLY_BRACKET_RIGHT },
+       {"~", "asciitilde", DIKS_TILDE },
+       {"\177", "Delete", DIKS_DELETE },
+       {"", "Left", DIKS_CURSOR_LEFT },
+       {"", "Right", DIKS_CURSOR_RIGHT},
+       {"", "Up", DIKS_CURSOR_UP},
+       {"", "Down", DIKS_CURSOR_DOWN},
+       {"", "Insert", DIKS_INSERT},
+       {"", "Home", DIKS_HOME},
+       {"", "End", DIKS_END},
+       {"", "Page_Up", DIKS_PAGE_UP},
+       {"", "Page_Down", DIKS_PAGE_DOWN},
+       {"", "Print", DIKS_PRINT},
+       {"", "Pause", DIKS_PAUSE},
+       /* ok */
+       {"", "Select",DIKS_SELECT},
+       /* goto */
+       {"", "Clear", DIKS_CLEAR},
+       /* power */
+       /* power 2 */
+       /* option */
+       {"", "Menu",DIKS_MENU},
+       {"", "Help",DIKS_HELP},
+       /* info */
+       /* time */
+       /* vendor */
+       /* archive */
+       /* program */
+       /* channel */
+       /* favorites */
+       /* hasta next */
+       {"", "Next",DIKS_NEXT},
+       {"", "Begin",DIKS_BEGIN},
+       /* digits */
+       /* teen */
+       /* twen */
+       {"", "Break", DIKS_BREAK},
+       /* exit */
+       /* setup */
+       {"", "upleftcorner", DIKS_CURSOR_LEFT_UP },
+       {"", "lowleftcorner", DIKS_CURSOR_LEFT_DOWN },
+       {"", "uprightcorner", DIKS_CURSOR_UP_RIGHT },
+       {"", "lowrightcorner",DIKS_CURSOR_DOWN_RIGHT },
+       {"", "F1",DIKS_F1},
+       {"", "F2",DIKS_F2},
+       {"", "F3",DIKS_F3},
+       {"", "F4",DIKS_F4},
+       {"", "F5",DIKS_F5},
+       {"", "F6",DIKS_F6},
+       {"", "F7",DIKS_F7},
+       {"", "F8",DIKS_F8},
+       {"", "F9",DIKS_F9},
+       {"", "F10",DIKS_F10},
+       {"", "F11",DIKS_F11},
+       {"", "F12",DIKS_F12},
+       /* this are only mapped to one, not left right */
+       {"", "Shift_L", DIKS_SHIFT},
+       /*{"Shift_R",0xFFE2},*/
+       {"", "Control_L", DIKS_CONTROL},
+       /*{"Control_R",0xFFE4},*/
+       {"", "Meta_L", DIKS_META},
+       /* {"Meta_R",0xFFE8},*/
+       {"", "Alt_L", DIKS_ALT},
+       {"", "Alt_R", DIKS_ALTGR},
+       {"", "Super_L", DIKS_SUPER},
+       /*{"Super_R",0xFFEC},*/
+       {"", "Hyper_L", DIKS_HYPER},
+       /*{"Hyper_R",0xFFEE},*/
+               
+       {"", "Caps_Lock", DIKS_CAPS_LOCK},
+       {"", "Num_Lock", DIKS_NUM_LOCK},
+       {"", "Scroll_Lock", DIKS_SCROLL_LOCK},
+       /* not included the dead keys */
+       /* not included the custom keys */
+       {"", "VoidSymbol", DIKS_NULL}
+};
+static int _ecore_directfb_key_symbols_count = sizeof(_ecore_directfb_key_symbols)/sizeof(Ecore_DirectFB_Key_Symbols);
diff --git a/src/lib/ecore_directfb/ecore_directfb_private.h b/src/lib/ecore_directfb/ecore_directfb_private.h
new file mode 100644 (file)
index 0000000..e9124aa
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _ECORE_DIRECTFB_PRIVATE_H
+#define _ECORE_DIRECTFB_PRIVATE_H
+/* eina_log related things */
+
+extern int _ecore_directfb_log_dom;
+
+#ifdef ECORE_DIRECTFB_DEFAULT_LOG_COLOR
+#undef ECORE_DIRECTFB_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_DIRECTFB_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_directfb_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_directfb_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_directfb_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_directfb_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_directfb_log_dom, __VA_ARGS__)
+
+/* macro for a safe call to DirectFB functions */
+#define DFBCHECK(x...) \
+     {                                                                 \
+          _err = x;                                                    \
+          if (_err != DFB_OK) {                                        \
+               CRIT("%s <%d>:\n\t", __FILE__, __LINE__ );              \
+               DirectFBErrorFatal( #x, _err );                         \
+          }                                                            \
+     }
+
+struct keymap
+{
+       char *name;
+       char *string;
+};
+#endif
diff --git a/src/lib/ecore_evas/.cvsignore b/src/lib/ecore_evas/.cvsignore
new file mode 100644 (file)
index 0000000..09980ae
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/ecore_evas/Ecore_Evas.h b/src/lib/ecore_evas/Ecore_Evas.h
new file mode 100644 (file)
index 0000000..a113bdb
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_EVAS_H
+#define _ECORE_EVAS_H
+
+#include <Evas.h>
+#include <Ecore_Getopt.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_EVAS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_EVAS_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file Ecore_Evas.h
+ * @brief Evas wrapper functions
+ */
+
+/* FIXME:
+ * to do soon:
+ * - iconfication api needs to work
+ * - maximization api needs to work
+ * - document all calls
+ *
+ * later:
+ * - buffer back-end that renders to an evas_image_object ???
+ * - qt back-end ???
+ * - dfb back-end ??? (dfb's threads make this REALLY HARD)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* these are dummy and just tell u what API levels ecore_evas supports - not if
+ * the actual support is compiled in. you need to query for that separately.
+ */
+#define HAVE_ECORE_EVAS_X 1
+#define HAVE_ECORE_EVAS_FB 1
+#define HAVE_ECORE_EVAS_X11_GL 1
+#define HAVE_ECORE_EVAS_X11_16 1
+#define HAVE_ECORE_EVAS_DIRECTFB 1
+#define HAVE_ECORE_EVAS_WIN32 1
+#define HAVE_ECORE_EVAS_COCOA 1
+#define HAVE_ECORE_EVAS_SDL 1
+#define HAVE_ECORE_EVAS_WINCE 1
+
+typedef enum _Ecore_Evas_Engine_Type
+{
+   ECORE_EVAS_ENGINE_SOFTWARE_BUFFER,
+   ECORE_EVAS_ENGINE_SOFTWARE_XLIB,
+   ECORE_EVAS_ENGINE_XRENDER_X11,
+   ECORE_EVAS_ENGINE_OPENGL_X11,
+   ECORE_EVAS_ENGINE_SOFTWARE_XCB,
+   ECORE_EVAS_ENGINE_XRENDER_XCB,
+   ECORE_EVAS_ENGINE_SOFTWARE_GDI,
+   ECORE_EVAS_ENGINE_SOFTWARE_DDRAW,
+   ECORE_EVAS_ENGINE_DIRECT3D,
+   ECORE_EVAS_ENGINE_OPENGL_GLEW,
+   ECORE_EVAS_ENGINE_COCOA,
+   ECORE_EVAS_ENGINE_SOFTWARE_SDL,
+   ECORE_EVAS_ENGINE_DIRECTFB,
+   ECORE_EVAS_ENGINE_SOFTWARE_FB,
+   ECORE_EVAS_ENGINE_SOFTWARE_16_X11,
+   ECORE_EVAS_ENGINE_SOFTWARE_16_DDRAW,
+   ECORE_EVAS_ENGINE_SOFTWARE_16_WINCE,
+   ECORE_EVAS_ENGINE_OPENGL_SDL
+} Ecore_Evas_Engine_Type;
+
+typedef enum _Ecore_Evas_Avoid_Damage_Type
+{
+   ECORE_EVAS_AVOID_DAMAGE_NONE = 0,
+   ECORE_EVAS_AVOID_DAMAGE_EXPOSE = 1,
+   ECORE_EVAS_AVOID_DAMAGE_BUILT_IN = 2
+} Ecore_Evas_Avoid_Damage_Type;
+
+typedef enum _Ecore_Evas_Object_Associate_Flags
+{
+  ECORE_EVAS_OBJECT_ASSOCIATE_BASE  = 0,
+  ECORE_EVAS_OBJECT_ASSOCIATE_STACK = 1 << 0,
+  ECORE_EVAS_OBJECT_ASSOCIATE_LAYER = 1 << 1,
+  ECORE_EVAS_OBJECT_ASSOCIATE_DEL = 1 << 2
+} Ecore_Evas_Object_Associate_Flags;
+
+#ifndef _ECORE_X_H
+#define _ECORE_X_WINDOW_PREDEF
+typedef unsigned int Ecore_X_Window;
+#endif
+
+#ifndef _ECORE_DIRECTFB_H
+#define _ECORE_DIRECTFB_WINDOW_PREDEF
+typedef struct _Ecore_DirectFB_Window Ecore_DirectFB_Window;
+#endif
+
+#ifndef __ECORE_WIN32_H__
+typedef struct _Ecore_Win32_Window Ecore_Win32_Window;
+#endif
+
+#ifndef __ECORE_WINCE_H__
+typedef void Ecore_WinCE_Window;
+#endif
+
+#ifndef _ECORE_EVAS_PRIVATE_H
+/* basic data types */
+typedef struct _Ecore_Evas Ecore_Evas;
+#endif
+
+#include <Ecore_Input.h>
+
+/* module setup/shutdown calls */
+
+EAPI int         ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine);
+
+EAPI int         ecore_evas_init(void);
+EAPI int         ecore_evas_shutdown(void);
+
+EAPI void        ecore_evas_app_comp_sync_set(int do_sync);
+EAPI int         ecore_evas_app_comp_sync_get(void);
+   
+EAPI Eina_List  *ecore_evas_engines_get(void);
+EAPI void        ecore_evas_engines_free(Eina_List *engines);
+EAPI Ecore_Evas *ecore_evas_new(const char *engine_name, int x, int y, int w, int h, const char *extra_options);
+
+
+/* engine/target specific init calls */
+EAPI Ecore_Evas     *ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window  ecore_evas_software_x11_window_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on);
+EAPI int             ecore_evas_software_x11_direct_resize_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win);
+
+#define ECORE_EVAS_GL_X11_OPT_NONE     0
+#define ECORE_EVAS_GL_X11_OPT_INDIRECT 1
+#define ECORE_EVAS_GL_X11_OPT_LAST     2
+
+EAPI Ecore_Evas     *ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_Evas     *ecore_evas_gl_x11_options_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h, const int *opt);
+EAPI Ecore_X_Window  ecore_evas_gl_x11_window_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, int on);
+EAPI int             ecore_evas_gl_x11_direct_resize_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_gl_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win);
+EAPI void            ecore_evas_gl_x11_pre_post_swap_callback_set(const Ecore_Evas *ee, void *data, void (*pre_cb) (void *data, Evas *e), void (*post_cb) (void *data, Evas *e));
+       
+EAPI Ecore_Evas     *ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window  ecore_evas_xrender_x11_window_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_xrender_x11_direct_resize_set(Ecore_Evas *ee, int on);
+EAPI int             ecore_evas_xrender_x11_direct_resize_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_xrender_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win);
+
+EAPI Ecore_Evas     *ecore_evas_software_x11_16_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window  ecore_evas_software_x11_16_window_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_software_x11_16_direct_resize_set(Ecore_Evas *ee, int on);
+EAPI int             ecore_evas_software_x11_16_direct_resize_get(const Ecore_Evas *ee);
+EAPI void            ecore_evas_software_x11_16_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win);
+
+EAPI Ecore_Evas     *ecore_evas_fb_new(const char *disp_name, int rotation, int w, int h);
+
+EAPI Ecore_Evas     *ecore_evas_directfb_new(const char *disp_name, int windowed, int x, int y, int w, int h);
+EAPI Ecore_DirectFB_Window *ecore_evas_directfb_window_get(const Ecore_Evas *ee);
+
+EAPI Ecore_Evas     *ecore_evas_buffer_new(int w, int h);
+EAPI const void     *ecore_evas_buffer_pixels_get(Ecore_Evas *ee);
+
+EAPI Evas_Object    *ecore_evas_object_image_new(Ecore_Evas *ee_target);
+
+EAPI Ecore_Evas     *ecore_evas_software_gdi_new(Ecore_Win32_Window *parent,
+                                                 int                 x,
+                                                 int                 y,
+                                                 int                 width,
+                                                 int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_ddraw_new(Ecore_Win32_Window *parent,
+                                                   int                 x,
+                                                   int                 y,
+                                                   int                 width,
+                                                   int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_16_ddraw_new(Ecore_Win32_Window *parent,
+                                                      int                 x,
+                                                      int                 y,
+                                                      int                 width,
+                                                      int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_direct3d_new(Ecore_Win32_Window *parent,
+                                             int                 x,
+                                             int                 y,
+                                             int                 width,
+                                             int                 height);
+
+EAPI Ecore_Evas *ecore_evas_gl_glew_new(Ecore_Win32_Window *parent,
+                                        int                 x,
+                                        int                 y,
+                                        int                 width,
+                                        int                 height);
+
+EAPI Ecore_Win32_Window *ecore_evas_win32_window_get(const Ecore_Evas *ee);
+
+EAPI Ecore_Evas     *ecore_evas_sdl_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha);
+EAPI Ecore_Evas     *ecore_evas_sdl16_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha);
+EAPI Ecore_Evas     *ecore_evas_gl_sdl_new(const char* name, int w, int h, int fullscreen, int noframe);
+
+EAPI Ecore_Evas     *ecore_evas_software_wince_new(Ecore_WinCE_Window *parent,
+                                                   int                 x,
+                                                   int                 y,
+                                                   int                 width,
+                                                   int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_wince_fb_new(Ecore_WinCE_Window *parent,
+                                                      int                 x,
+                                                      int                 y,
+                                                      int                 width,
+                                                      int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_wince_gapi_new(Ecore_WinCE_Window *parent,
+                                                        int                 x,
+                                                        int                 y,
+                                                        int                 width,
+                                                        int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_wince_ddraw_new(Ecore_WinCE_Window *parent,
+                                                         int                 x,
+                                                         int                 y,
+                                                         int                 width,
+                                                         int                 height);
+
+EAPI Ecore_Evas     *ecore_evas_software_wince_gdi_new(Ecore_WinCE_Window *parent,
+                                                       int                 x,
+                                                       int                 y,
+                                                       int                 width,
+                                                       int                 height);
+
+EAPI Ecore_WinCE_Window *ecore_evas_software_wince_window_get(const Ecore_Evas *ee);
+
+EAPI Ecore_Evas *ecore_evas_cocoa_new(const char* name, int w, int h);
+
+/* generic manipulation calls */
+EAPI const char *ecore_evas_engine_name_get(const Ecore_Evas *ee);
+EAPI Ecore_Evas *ecore_evas_ecore_evas_get(const Evas *e);
+EAPI void        ecore_evas_free(Ecore_Evas *ee);
+EAPI void       *ecore_evas_data_get(const Ecore_Evas *ee, const char *key);
+EAPI void        ecore_evas_data_set(Ecore_Evas *ee, const char *key, const void *data);
+EAPI void        ecore_evas_callback_resize_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_move_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_show_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_hide_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_destroy_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_focus_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_focus_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_sticky_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_unsticky_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_mouse_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_mouse_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_pre_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_post_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI void        ecore_evas_callback_pre_free_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+EAPI Evas       *ecore_evas_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_move(Ecore_Evas *ee, int x, int y);
+EAPI void        ecore_evas_managed_move(Ecore_Evas *ee, int x, int y);
+EAPI void        ecore_evas_resize(Ecore_Evas *ee, int w, int h);
+EAPI void        ecore_evas_move_resize(Ecore_Evas *ee, int x, int y, int w, int h);
+EAPI void        ecore_evas_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h);
+EAPI void        ecore_evas_rotation_set(Ecore_Evas *ee, int rot);
+EAPI void        ecore_evas_rotation_with_resize_set(Ecore_Evas *ee, int rot);
+EAPI int         ecore_evas_rotation_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_shaped_set(Ecore_Evas *ee, int shaped);
+EAPI int         ecore_evas_shaped_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_alpha_set(Ecore_Evas *ee, int alpha);
+EAPI int         ecore_evas_alpha_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_transparent_set(Ecore_Evas *ee, int transparent);
+EAPI int         ecore_evas_transparent_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_show(Ecore_Evas *ee);
+EAPI void        ecore_evas_hide(Ecore_Evas *ee);
+EAPI int         ecore_evas_visibility_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_raise(Ecore_Evas *ee);
+EAPI void        ecore_evas_lower(Ecore_Evas *ee);
+EAPI void        ecore_evas_activate(Ecore_Evas *ee);
+EAPI void        ecore_evas_title_set(Ecore_Evas *ee, const char *t);
+EAPI const char *ecore_evas_title_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_name_class_set(Ecore_Evas *ee, const char *n, const char *c);
+EAPI void        ecore_evas_name_class_get(const Ecore_Evas *ee, const char **n, const char **c);
+EAPI void        ecore_evas_size_min_set(Ecore_Evas *ee, int w, int h);
+EAPI void        ecore_evas_size_min_get(const Ecore_Evas *ee, int *w, int *h);
+EAPI void        ecore_evas_size_max_set(Ecore_Evas *ee, int w, int h);
+EAPI void        ecore_evas_size_max_get(const Ecore_Evas *ee, int *w, int *h);
+EAPI void        ecore_evas_size_base_set(Ecore_Evas *ee, int w, int h);
+EAPI void        ecore_evas_size_base_get(const Ecore_Evas *ee, int *w, int *h);
+EAPI void        ecore_evas_size_step_set(Ecore_Evas *ee, int w, int h);
+EAPI void        ecore_evas_size_step_get(const Ecore_Evas *ee, int *w, int *h);
+EAPI void        ecore_evas_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y);
+EAPI void        ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y);
+EAPI void        ecore_evas_cursor_get(const Ecore_Evas *ee, Evas_Object **obj, int *layer, int *hot_x, int *hot_y);
+EAPI void        ecore_evas_layer_set(Ecore_Evas *ee, int layer);
+EAPI int         ecore_evas_layer_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_focus_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_focus_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_iconified_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_iconified_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_borderless_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_borderless_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_override_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_override_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_maximized_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_maximized_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_fullscreen_set(Ecore_Evas *ee, int on);
+EAPI int         ecore_evas_fullscreen_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_avoid_damage_set(Ecore_Evas *ee, Ecore_Evas_Avoid_Damage_Type on);
+EAPI Ecore_Evas_Avoid_Damage_Type ecore_evas_avoid_damage_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_withdrawn_set(Ecore_Evas *ee, int withdrawn);
+EAPI int         ecore_evas_withdrawn_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_sticky_set(Ecore_Evas *ee, int sticky);
+EAPI int         ecore_evas_sticky_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_ignore_events_set(Ecore_Evas *ee, int ignore);
+EAPI int         ecore_evas_ignore_events_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_manual_render_set(Ecore_Evas *ee, int manual_render);
+EAPI int         ecore_evas_manual_render_get(const Ecore_Evas *ee);
+EAPI void        ecore_evas_manual_render(Ecore_Evas *ee);
+EAPI void        ecore_evas_comp_sync_set(Ecore_Evas *ee, int do_sync);
+EAPI int         ecore_evas_comp_sync_get(const Ecore_Evas *ee);
+       
+EAPI Ecore_Window ecore_evas_window_get(const Ecore_Evas *ee);
+
+
+EAPI int          ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags);
+EAPI int          ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj);
+EAPI Evas_Object *ecore_evas_object_associate_get(const Ecore_Evas *ee);
+
+/* helper function to be used with ECORE_GETOPT_CALLBACK_*() */
+EAPI unsigned char ecore_getopt_callback_ecore_evas_list_engines(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, const char *str, void *data, Ecore_Getopt_Value *storage);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_evas/Makefile.am b/src/lib/ecore_evas/Makefile.am
new file mode 100644 (file)
index 0000000..adabce7
--- /dev/null
@@ -0,0 +1,124 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_X
+ECORE_X_INC = -I$(top_srcdir)/src/lib/ecore_x @x_cflags@ @XRENDER_CFLAGS@ @XCB_CFLAGS@ @XCB_RENDER_CFLAGS@
+ECORE_X_LIB = $(top_builddir)/src/lib/ecore_x/libecore_x.la @x_libs@ @XRENDER_LIBS@ @XCB_LIBS@ @XCB_RENDER_LIBS@
+else
+ECORE_X_INC =
+ECORE_X_LIB =
+endif
+
+if BUILD_ECORE_FB
+ECORE_FB_INC = -I$(top_srcdir)/src/lib/ecore_fb
+ECORE_FB_LIB = $(top_builddir)/src/lib/ecore_fb/libecore_fb.la
+else
+ECORE_FB_INC =
+ECORE_FB_LIB =
+endif
+
+if BUILD_ECORE_DIRECTFB
+ECORE_DIRECTFB_INC = -I$(top_srcdir)/src/lib/ecore_directfb -I@DIRECTFB_CFLAGS@
+ECORE_DIRECTFB_LIB = $(top_builddir)/src/lib/ecore_directfb/libecore_directfb.la
+else
+ECORE_DIRECTFB_INC =
+ECORE_DIRECTFB_LIB =
+endif
+
+if BUILD_ECORE_WIN32
+ECORE_WIN32_INC = -I$(top_srcdir)/src/lib/ecore_win32
+ECORE_WIN32_LIB = $(top_builddir)/src/lib/ecore_win32/libecore_win32.la
+else
+ECORE_WIN32_INC =
+ECORE_WIN32_LIB =
+endif
+
+if BUILD_ECORE_SDL
+ECORE_SDL_INC = -I$(top_srcdir)/src/lib/ecore_sdl @SDL_CFLAGS@
+ECORE_SDL_LIB = $(top_builddir)/src/lib/ecore_sdl/libecore_sdl.la
+ECORE_SDL_LIBADD = @SDL_LIBS@ $(ECORE_SDL_LIB)
+else
+ECORE_SDL_INC =
+ECORE_SDL_LIB =
+ECORE_SDL_LIBADD =
+endif
+
+if BUILD_ECORE_COCOA
+ECORE_COCOA_INC = -I$(top_srcdir)/src/lib/ecore_cocoa -xobjective-c
+ECORE_COCOA_LIB = $(top_builddir)/src/lib/ecore_cocoa/libecore_cocoa.la
+else
+ECORE_COCOA_INC =
+ECORE_COCOA_LIB =
+endif
+
+if BUILD_ECORE_WINCE
+ECORE_WINCE_INC = -I$(top_srcdir)/src/lib/ecore_wince
+ECORE_WINCE_LIB = $(top_builddir)/src/lib/ecore_wince/libecore_wince.la
+else
+ECORE_WINCE_INC =
+ECORE_WINCE_LIB =
+endif
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_evas \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_srcdir)/src/lib/ecore_input_evas \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_evas \
+-I$(top_builddir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore_input_evas \
+@EFL_ECORE_EVAS_BUILD@ \
+$(ECORE_X_INC) \
+$(ECORE_FB_INC) \
+$(ECORE_DIRECTFB_INC) \
+$(ECORE_WIN32_INC) \
+$(ECORE_SDL_INC) \
+$(ECORE_COCOA_INC) \
+$(ECORE_WINCE_INC) \
+@EVAS_CFLAGS@ \
+@XCB_CFLAGS@ \
+@EINA_CFLAGS@ \
+@EVIL_CFLAGS@
+
+AM_CFLAGS = @WIN32_CFLAGS@
+
+if BUILD_ECORE_EVAS
+
+lib_LTLIBRARIES = libecore_evas.la
+include_HEADERS = \
+Ecore_Evas.h
+
+libecore_evas_la_SOURCES = \
+ecore_evas.c \
+ecore_evas_util.c \
+ecore_evas_x.c \
+ecore_evas_fb.c \
+ecore_evas_buffer.c \
+ecore_evas_directfb.c \
+ecore_evas_win32.c \
+ecore_evas_sdl.c \
+ecore_evas_cocoa.c \
+ecore_evas_wince.c
+
+libecore_evas_la_LIBADD = \
+$(ECORE_X_LIB) \
+$(ECORE_FB_LIB) \
+$(ECORE_DIRECTFB_LIB) \
+$(ECORE_WIN32_LIB) \
+$(ECORE_SDL_LIB) \
+$(ECORE_SDL_LIBADD) \
+$(ECORE_COCOA_LIB) \
+$(ECORE_WINCE_LIB) \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+$(top_builddir)/src/lib/ecore_input_evas/libecore_input_evas.la \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@ \
+@EVIL_LIBS@
+
+libecore_evas_la_LDFLAGS = @cocoa_ldflags@ -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_evas_release_info@
+
+endif
+
+EXTRA_DIST = \
+ecore_evas_private.h
diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c
new file mode 100644 (file)
index 0000000..eda08f3
--- /dev/null
@@ -0,0 +1,2860 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Input.h"
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+int _ecore_evas_log_dom = -1;
+static int _ecore_evas_init_count = 0;
+static Ecore_Fd_Handler *_ecore_evas_async_events_fd = NULL;
+static int _ecore_evas_async_events_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
+static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL;
+static Ecore_Evas *ecore_evases = NULL;
+static int _ecore_evas_fps_debug = 0;
+
+static int
+_ecore_evas_idle_enter(void *data __UNUSED__)
+{
+   Ecore_Evas *ee;
+   double t1 = 0.0;
+   double t2 = 0.0;
+   int rend = 0;
+   
+   if (!ecore_evases) return 1;
+   if (_ecore_evas_fps_debug)
+     {
+        t1 = ecore_time_get();
+     }
+   EINA_INLIST_FOREACH(ecore_evases, ee)
+     {
+        if (!ee->manual_render)
+          {
+             if (ee->engine.func->fn_render)
+               rend |= ee->engine.func->fn_render(ee);
+          }
+     }
+   if (_ecore_evas_fps_debug)
+     {
+        t2 = ecore_time_get();
+        if (rend)
+          _ecore_evas_fps_debug_rendertime_add(t2 - t1);
+     }
+   return 1;
+}
+
+/**
+ * Query if a particular renginering engine target has support
+ * @param  engine The engine to check support for
+ * @return 1 if the particualr engine is supported, 0 if it is not
+ *
+ * Query if engine @param engine is supported by ecore_evas. 1 is returned if
+ * it is, and 0 is returned if it is not supported.
+ */
+EAPI int
+ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine)
+{
+   switch (engine)
+     {
+      case ECORE_EVAS_ENGINE_SOFTWARE_BUFFER:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_XLIB:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_XLIB
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_XRENDER_X11:
+#ifdef BUILD_ECORE_EVAS_XRENDER_X11
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_OPENGL_X11:
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_XCB:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_XRENDER_XCB:
+#ifdef BUILD_ECORE_EVAS_XRENDER_XCB
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_GDI:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_DDRAW:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_DIRECT3D:
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_OPENGL_GLEW:
+#ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+       return 1;
+#else
+       return 0;
+#endif
+     case ECORE_EVAS_ENGINE_SOFTWARE_SDL:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+        return 1;
+#else
+        return 0;
+#endif
+     case ECORE_EVAS_ENGINE_OPENGL_SDL:
+#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+        return 1;
+#else
+        return 0;
+#endif
+      case ECORE_EVAS_ENGINE_DIRECTFB:
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_FB:
+#ifdef BUILD_ECORE_EVAS_FB
+       return 1;
+#else
+       return 0;
+#endif
+
+      case ECORE_EVAS_ENGINE_SOFTWARE_16_X11:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_X11
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_16_DDRAW:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_SOFTWARE_16_WINCE:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+       return 1;
+#else
+       return 0;
+#endif
+      case ECORE_EVAS_ENGINE_COCOA:
+#ifdef BUILD_ECORE_EVAS_COCOA
+        return 1;
+#else
+        return 0;
+#endif
+      default:
+       return 0;
+       break;
+     };
+}
+
+/**
+ * Init the Evas system.
+ * @return greater than 0 on success, 0 on failure
+ *
+ * Set up the Evas wrapper system. Init Evas and Ecore libraries.
+ */
+EAPI int
+ecore_evas_init(void)
+{
+   int fd;
+
+   if (++_ecore_evas_init_count != 1)
+     return _ecore_evas_init_count;
+
+   if (!evas_init())
+     return --_ecore_evas_init_count;
+
+   if (!ecore_init())
+     goto shutdown_evas;
+
+   _ecore_evas_log_dom = eina_log_domain_register("Ecore_Evas", ECORE_EVAS_DEFAULT_LOG_COLOR);
+   if(_ecore_evas_log_dom < 0) 
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for Ecore_Evas.");
+       goto shutdown_ecore;
+     }
+
+   fd = evas_async_events_fd_get();
+   if (fd > 0)
+     _ecore_evas_async_events_fd = ecore_main_fd_handler_add(fd,
+                                                            ECORE_FD_READ,
+                                                            _ecore_evas_async_events_fd_handler, NULL,
+                                                            NULL, NULL);
+   
+   ecore_evas_idle_enterer = 
+     ecore_idle_enterer_add(_ecore_evas_idle_enter, NULL);
+   if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1;
+   if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init();
+   
+   return _ecore_evas_init_count;
+
+ shutdown_ecore:
+   ecore_shutdown();
+ shutdown_evas:
+   evas_shutdown();
+
+   return --_ecore_evas_init_count;
+}
+
+/**
+ * Shut down the Evas system.
+ * @return 0 if ecore evas is fully shut down, or > 0 if it still needs to be shut down
+ *
+ * This closes the Evas wrapper system down. Shut down Evas and Ecore libraries.
+ */
+EAPI int
+ecore_evas_shutdown(void)
+{
+   if (--_ecore_evas_init_count != 0)
+     return _ecore_evas_init_count;
+
+   while (ecore_evases) _ecore_evas_free(ecore_evases);
+
+   if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown();
+   ecore_idle_enterer_del(ecore_evas_idle_enterer);
+   ecore_evas_idle_enterer = NULL;
+
+#ifdef BUILD_ECORE_EVAS_X11
+   while (_ecore_evas_x_shutdown());
+#endif
+#ifdef BUILD_ECORE_EVAS_WIN32
+   while (_ecore_evas_win32_shutdown());
+#endif
+#ifdef BUILD_ECORE_EVAS_FB
+   while (_ecore_evas_fb_shutdown());
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   while (_ecore_evas_buffer_shutdown());
+#endif
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+   while (_ecore_evas_directfb_shutdown());
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+   while (_ecore_evas_wince_shutdown());
+#endif
+   if (_ecore_evas_async_events_fd)
+     ecore_main_fd_handler_del(_ecore_evas_async_events_fd);
+
+   eina_log_domain_unregister(_ecore_evas_log_dom);
+   _ecore_evas_log_dom = -1;
+   ecore_shutdown();
+   evas_shutdown();
+
+   return _ecore_evas_init_count;
+}
+
+int _ecore_evas_app_comp_sync = 1;
+
+EAPI void
+ecore_evas_app_comp_sync_set(int do_sync)
+{
+   _ecore_evas_app_comp_sync = do_sync;
+}
+
+EAPI int
+ecore_evas_app_comp_sync_get(void)
+{
+   return _ecore_evas_app_comp_sync;
+}
+
+struct ecore_evas_engine {
+   const char *name;
+   Ecore_Evas *(*constructor)(int x, int y, int w, int h, const char *extra_options);
+};
+
+/* inline is just to avoid need to ifdef around it */
+static inline const char *
+_ecore_evas_parse_extra_options_str(const char *extra_options, const char *key, char **value)
+{
+   int len = strlen(key);
+
+   while (extra_options)
+     {
+       const char *p;
+
+       if (strncmp(extra_options, key, len) != 0)
+         {
+            extra_options = strchr(extra_options, ';');
+            if (extra_options)
+              extra_options++;
+            continue;
+         }
+
+       extra_options += len;
+       p = strchr(extra_options, ';');
+       if (p)
+         {
+            len = p - extra_options;
+            *value = malloc(len + 1);
+            memcpy(*value, extra_options, len);
+            (*value)[len] = '\0';
+            extra_options = p + 1;
+         }
+       else
+         {
+            *value = strdup(extra_options);
+            extra_options = NULL;
+         }
+     }
+   return extra_options;
+}
+
+/* inline is just to avoid need to ifdef around it */
+static inline const char *
+_ecore_evas_parse_extra_options_uint(const char *extra_options, const char *key, unsigned int *value)
+{
+   int len = strlen(key);
+
+   while (extra_options)
+     {
+       const char *p;
+
+       if (strncmp(extra_options, key, len) != 0)
+         {
+            extra_options = strchr(extra_options, ';');
+            if (extra_options)
+              extra_options++;
+            continue;
+         }
+
+       extra_options += len;
+       *value = strtol(extra_options, NULL, 0);
+
+       p = strchr(extra_options, ';');
+       if (p)
+         extra_options = p + 1;
+       else
+         extra_options = NULL;
+     }
+   return extra_options;
+}
+
+/* inline is just to avoid need to ifdef around it */
+static inline const char *
+_ecore_evas_parse_extra_options_x(const char *extra_options, char **disp_name, unsigned int *parent)
+{
+   _ecore_evas_parse_extra_options_str(extra_options, "display=", disp_name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "parent=", parent);
+   return extra_options;
+}
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+static Ecore_Evas *
+_ecore_evas_constructor_software_x11(int x, int y, int w, int h, const char *extra_options)
+{
+   unsigned int parent = 0;
+   char *disp_name = NULL;
+   Ecore_Evas *ee;
+
+   _ecore_evas_parse_extra_options_x(extra_options, &disp_name, &parent);
+   ee = ecore_evas_software_x11_new(disp_name, parent, x, y, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_COCOA
+static Ecore_Evas *
+_ecore_evas_constructor_cocoa(int x, int y, int w, int h, const char *extra_options)
+{
+   char *name = NULL;
+   Ecore_Evas *ee;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "name=", &name);
+   ee = ecore_evas_cocoa_new(name, w, h);
+   free(name);
+
+   if (ee) ecore_evas_move(ee, x, y);
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_XRENDER_X11
+static Ecore_Evas *
+_ecore_evas_constructor_xrender_x11(int x, int y, int w, int h, const char *extra_options)
+{
+   unsigned int parent = 0;
+   char *disp_name = NULL;
+   Ecore_Evas *ee;
+
+   _ecore_evas_parse_extra_options_x(extra_options, &disp_name, &parent);
+   ee = ecore_evas_xrender_x11_new(disp_name, parent, x, y, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+static Ecore_Evas *
+_ecore_evas_constructor_opengl_x11(int x, int y, int w, int h, const char *extra_options)
+{
+   Ecore_X_Window parent = 0;
+   char *disp_name = NULL;
+   Ecore_Evas *ee;
+
+   _ecore_evas_parse_extra_options_x(extra_options, &disp_name, &parent);
+   ee = ecore_evas_gl_x11_new(disp_name, parent, x, y, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_X11
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_x11(int x, int y, int w, int h, const char *extra_options)
+{
+   Ecore_X_Window parent = 0;
+   char *disp_name = NULL;
+   Ecore_Evas *ee;
+
+   _ecore_evas_parse_extra_options_x(extra_options, &disp_name, &parent);
+   ee = ecore_evas_software_x11_16_new(disp_name, parent, x, y, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+static Ecore_Evas *
+_ecore_evas_constructor_sdl(int x __UNUSED__, int y __UNUSED__, int w, int h, const char *extra_options)
+{
+   Ecore_Evas *ee;
+   unsigned int fullscreen = 0, hwsurface = 0, noframe = 0, alpha = 0;
+   char *name = NULL;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "name=", &name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "fullscreen=", &fullscreen);
+   _ecore_evas_parse_extra_options_uint(extra_options, "hwsurface=", &hwsurface);
+   _ecore_evas_parse_extra_options_uint(extra_options, "alpha=", &alpha);
+
+   ee = ecore_evas_sdl_new(name, w, h, fullscreen, hwsurface, noframe, alpha);
+   free(name);
+
+   return ee;
+}
+
+static Ecore_Evas *
+_ecore_evas_constructor_sdl16(int x __UNUSED__, int y __UNUSED__, int w, int h, const char *extra_options)
+{
+   Ecore_Evas *ee;
+   unsigned int fullscreen = 0, hwsurface = 0, noframe = 0, alpha = 0;
+   char *name = NULL;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "name=", &name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "fullscreen=", &fullscreen);
+   _ecore_evas_parse_extra_options_uint(extra_options, "hwsurface=", &hwsurface);
+   _ecore_evas_parse_extra_options_uint(extra_options, "alpha=", &alpha);
+
+   ee = ecore_evas_sdl16_new(name, w, h, fullscreen, hwsurface, noframe, alpha);
+   free(name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+static Ecore_Evas *
+_ecore_evas_constructor_opengl_sdl(int x __UNUSED__, int y __UNUSED__, int w, int h, const char *extra_options)
+{
+   Ecore_Evas *ee;
+   unsigned int fullscreen = 0, noframe = 0;
+   char *name = NULL;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "name=", &name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "fullscreen=", &fullscreen);
+   _ecore_evas_parse_extra_options_uint(extra_options, "noframe=", &noframe);
+
+   ee = ecore_evas_gl_sdl_new(name, w, h, fullscreen, noframe);
+   free(name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+static Ecore_Evas *
+_ecore_evas_constructor_directfb(int x, int y, int w, int h, const char *extra_options)
+{
+   Ecore_Evas *ee;
+   char *disp_name = NULL;
+   unsigned int windowed = 1;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "display=", &disp_name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "windowed=", &windowed);
+
+   ee = ecore_evas_directfb_new(disp_name, windowed, x, y, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_FB
+static Ecore_Evas *
+_ecore_evas_constructor_fb(int x __UNUSED__, int y __UNUSED__, int w, int h, const char *extra_options)
+{
+   Ecore_Evas *ee;
+   char *disp_name = NULL;
+   unsigned int rotation = 0;
+
+   _ecore_evas_parse_extra_options_str(extra_options, "display=", &disp_name);
+   _ecore_evas_parse_extra_options_uint(extra_options, "rotation=", &rotation);
+
+   ee = ecore_evas_fb_new(disp_name, rotation, w, h);
+   free(disp_name);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+static Ecore_Evas *
+_ecore_evas_constructor_software_gdi(int x, int y, int w, int h, const char *extra_options)
+{
+   return ecore_evas_software_gdi_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+static Ecore_Evas *
+_ecore_evas_constructor_software_ddraw(int x, int y, int w, int h, const char *extra_options)
+{
+   return ecore_evas_software_ddraw_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+static Ecore_Evas *
+_ecore_evas_constructor_direct3d(int x, int y, int w, int h, const char *extra_options)
+{
+   return ecore_evas_direct3d_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+static Ecore_Evas *
+_ecore_evas_constructor_opengl_glew(int x, int y, int w, int h, const char *extra_options)
+{
+   return ecore_evas_gl_glew_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_ddraw(int x, int y, int w, int h, const char *extra_options)
+{
+   return ecore_evas_software_16_ddraw_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_wince(int x, int y, int w, int h, const char *extra_options __UNUSED__)
+{
+   return ecore_evas_software_wince_new(NULL, x, y, w, h);
+}
+
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_wince_fb(int x, int y, int w, int h, const char *extra_options __UNUSED__)
+{
+   return ecore_evas_software_wince_fb_new(NULL, x, y, w, h);
+}
+
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_wince_gapi(int x, int y, int w, int h, const char *extra_options __UNUSED__)
+{
+   return ecore_evas_software_wince_gapi_new(NULL, x, y, w, h);
+}
+
+static Ecore_Evas *
+_ecore_evas_constructor_software_16_wince_gdi(int x, int y, int w, int h, const char *extra_options __UNUSED__)
+{
+   return ecore_evas_software_wince_gdi_new(NULL, x, y, w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+static Ecore_Evas *
+_ecore_evas_constructor_buffer(int x __UNUSED__, int y __UNUSED__, int w, int h, const char *extra_options __UNUSED__)
+{
+   return ecore_evas_buffer_new(w, h);
+}
+#endif
+
+/* note: keep sorted by priority, highest first */
+static const struct ecore_evas_engine _engines[] = {
+  /* unix */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+  {"software_x11", _ecore_evas_constructor_software_x11},
+#endif
+#ifdef BUILD_ECORE_EVAS_XRENDER_X11
+  {"xrender_x11", _ecore_evas_constructor_xrender_x11},
+#endif
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+  {"opengl_x11", _ecore_evas_constructor_opengl_x11},
+#endif
+#ifdef BUILD_ECORE_EVAS_XRENDER_XCB
+  {"xrender_xcb", _ecore_evas_constructor_xrender_x11},
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_X11
+  {"software_16_x11", _ecore_evas_constructor_software_16_x11},
+#endif
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+  {"directfb", _ecore_evas_constructor_directfb},
+#endif
+#ifdef BUILD_ECORE_EVAS_FB
+  {"fb", _ecore_evas_constructor_fb},
+#endif
+
+  /* windows */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+  {"software_gdi", _ecore_evas_constructor_software_gdi},
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+  {"software_ddraw", _ecore_evas_constructor_software_ddraw},
+#endif
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+  {"direct3d", _ecore_evas_constructor_direct3d},
+#endif
+#ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+  {"opengl_glew", _ecore_evas_constructor_opengl_glew},
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+  {"software_16_ddraw", _ecore_evas_constructor_software_16_ddraw},
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+  {"software_16_wince", _ecore_evas_constructor_software_16_wince},
+  {"software_16_wince_fb", _ecore_evas_constructor_software_16_wince_fb},
+  {"software_16_wince_gapi", _ecore_evas_constructor_software_16_wince_gapi},
+  {"software_16_wince_gdi", _ecore_evas_constructor_software_16_wince_gdi},
+#endif
+
+  /* Apple */
+#ifdef BUILD_ECORE_EVAS_COCOA
+  {"cocoa", _ecore_evas_constructor_cocoa},
+#endif
+
+  /* Last chance to have a window */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+  {"sdl", _ecore_evas_constructor_sdl},
+  {"software_16_sdl", _ecore_evas_constructor_sdl16},
+#endif
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+  {"opengl_sdl", _ecore_evas_constructor_opengl_sdl},
+#endif
+
+  /* independent */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+  {"buffer", _ecore_evas_constructor_buffer},
+#endif
+  {NULL, NULL}
+};
+
+/**
+ * Returns a list of supported engines names.
+ *
+ * @return newly allocated list with engines names. Engines names
+ * strings are internal and should be considered constants, do not
+ * free them, to avoid problems use ecore_evas_engines_free()
+ */
+EAPI Eina_List *
+ecore_evas_engines_get(void)
+{
+   const struct ecore_evas_engine *itr;
+   Eina_List *lst = NULL;
+
+   for (itr = _engines; itr->name != NULL; itr++)
+     lst = eina_list_append(lst, itr->name);
+
+   return lst;
+}
+
+/**
+ * Free list returned by ecore_evas_engines_get()
+ */
+EAPI void
+ecore_evas_engines_free(Eina_List *engines)
+{
+   eina_list_free(engines);
+}
+
+static Ecore_Evas *
+_ecore_evas_new_auto_discover(int x, int y, int w, int h, const char *extra_options)
+{
+   const struct ecore_evas_engine *itr;
+
+   DBG("auto discover engine");
+
+   for (itr = _engines; itr->constructor != NULL; itr++)
+     {
+       Ecore_Evas *ee = itr->constructor(x, y, w, h, extra_options);
+       if (ee)
+         {
+            INF("auto discovered '%s'", itr->name);
+            return ee;
+         }
+     }
+
+   WRN("could not auto discover.");
+   return NULL;
+}
+
+/**
+ * Creates a new Ecore_Evas based on engine name and common parameters.
+ *
+ * @param engine_name engine name as returned by
+ *        ecore_evas_engines_get() or NULL to use environment variable
+ *        ECORE_EVAS_ENGINE, that can be undefined and in this case
+ *        this call will try to find the first working engine.
+ * @param x horizontal position of window (not supported in all engines)
+ * @param y vertical position of window (not supported in all engines)
+ * @param w width of window
+ * @param h height of window
+ * @param extra_options string with extra parameter, dependent on engines
+ *        or NULL. String is usually in the form: 'key1=value1;key2=value2'.
+ *        Pay attention that when getting that from shell commands, most
+ *        consider ';' as the command terminator, so you need to escape
+ *        it or use quotes.
+ *
+ * @return Ecore_Evas instance or NULL if creation failed.
+ */
+EAPI Ecore_Evas *
+ecore_evas_new(const char *engine_name, int x, int y, int w, int h, const char *extra_options)
+{
+   const struct ecore_evas_engine *itr;
+
+   if (!engine_name)
+     {
+       engine_name = getenv("ECORE_EVAS_ENGINE");
+       if (engine_name)
+         DBG("no engine_name provided, using ECORE_EVAS_ENGINE='%s'",
+             engine_name);
+     }
+   if (!engine_name)
+     return _ecore_evas_new_auto_discover(x, y, w, h, extra_options);
+
+   for (itr = _engines; itr->name != NULL; itr++)
+     if (strcmp(itr->name, engine_name) == 0)
+       {
+         INF("using engine '%s', extra_options=%s",
+             engine_name, extra_options ? extra_options : "(null)");
+         return itr->constructor(x, y, w, h, extra_options);
+       }
+
+   WRN("unknown engine '%s'", engine_name);
+   return NULL;
+}
+
+/**
+ * Get the engine name used by this engine.
+ *
+ * should return one of the values in ecore_evas_engines_get(), usually
+ * acceptable by ecore_evas_new().
+ */
+EAPI const char *
+ecore_evas_engine_name_get(const Ecore_Evas *ee)
+{
+   if (!ee)
+     return NULL;
+   return ee->driver;
+}
+
+/**
+ * Return the Ecore_Evas for this Evas
+ *
+ * @param e The Evas to get the Ecore_Evas from
+ * @return The Ecore_Evas that holds this Evas
+ */
+EAPI Ecore_Evas *
+ecore_evas_ecore_evas_get(const Evas *e)
+{
+   return evas_data_attach_get(e);
+}
+
+/**
+ * Free an Ecore_Evas
+ * @param ee The Ecore_Evas to free
+ *
+ * This frees up any memory used by the Ecore_Evas.
+ */
+EAPI void
+ecore_evas_free(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_free");
+       return;
+     }
+   _ecore_evas_free(ee);
+   return;
+}
+
+/**
+ * Retrieve user data associated with an Ecore_Evas.
+ * @param ee The Ecore_Evas to retrieve the user data from.
+ * @param key The key which the user data to be retrieved is associated with.
+ *
+ * This function retrieves user specific data that has been stored within an
+ * Ecore_Evas structure with ecore_evas_data_set().
+ *
+ * @returns NULL on error or no data found, A pointer to the user data on
+ *     success.
+ *
+ * @see ecore_evas_data_set
+ */
+EAPI void *
+ecore_evas_data_get(const Ecore_Evas *ee, const char *key)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_data_get");
+       return NULL;
+     }
+
+   if (!key) return NULL;
+   if (!ee->data) return NULL;
+
+   return eina_hash_find(ee->data, key);
+}
+
+/**
+ * Store user data in an Ecore_Evas structure.
+ *
+ * @param ee The Ecore_Evas to store the user data in.
+ * @param key A unique string to associate the user data against. Cannot
+ * be NULL.
+ * @param data A pointer to the user data to store.
+ *
+ * This function associates the @p data with a @p key which is stored by
+ * the Ecore_Evas @p ee. Be aware that a call to ecore_evas_free() will
+ * not free any memory for the associated user data, this is the responsibility
+ * of the caller.
+ *
+ * @see ecore_evas_free
+ */
+EAPI void
+ecore_evas_data_set(Ecore_Evas *ee, const char *key, const void *data)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_data_set");
+       return;
+     }
+
+   if (!key) return;
+
+   if (ee->data)
+     eina_hash_del(ee->data, key, NULL);
+   if (data)
+     {
+       if (!ee->data)
+        ee->data = eina_hash_string_superfast_new(NULL);
+       eina_hash_add(ee->data, key, data);
+     }
+}
+
+#define IFC(_ee, _fn)  if (_ee->engine.func->_fn) {_ee->engine.func->_fn
+#define IFE            return;}
+
+/**
+ * Set a callback for Ecore_Evas resize events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee is resized.
+ */
+EAPI void
+ecore_evas_callback_resize_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_resize_set");
+       return;
+     }
+   IFC(ee, fn_callback_resize_set) (ee, func);
+   IFE;
+   ee->func.fn_resize = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas move events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee is moved.
+ */
+EAPI void
+ecore_evas_callback_move_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_move_set");
+       return;
+     }
+   IFC(ee, fn_callback_move_set) (ee, func);
+   IFE;
+   ee->func.fn_move = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas show events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee is shown.
+ */
+EAPI void
+ecore_evas_callback_show_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_show_set");
+       return;
+     }
+   IFC(ee, fn_callback_show_set) (ee, func);
+   IFE;
+   ee->func.fn_show = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas hide events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee is hidden.
+ */
+EAPI void
+ecore_evas_callback_hide_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_hide_set");
+       return;
+     }
+   IFC(ee, fn_callback_hide_set) (ee, func);
+   IFE;
+   ee->func.fn_hide = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas delete request events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee gets a delete request.
+ */
+EAPI void
+ecore_evas_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_delete_request_set");
+       return;
+     }
+   IFC(ee, fn_callback_delete_request_set) (ee, func);
+   IFE;
+   ee->func.fn_delete_request = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas destroy events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee is destroyed.
+ */
+EAPI void
+ecore_evas_callback_destroy_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_destroy_set");
+       return;
+     }
+   IFC(ee, fn_callback_destroy_set) (ee, func);
+   IFE;
+   ee->func.fn_destroy = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas focus in events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee gets focus.
+ */
+EAPI void
+ecore_evas_callback_focus_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_focus_in_set");
+       return;
+     }
+   IFC(ee, fn_callback_focus_in_set) (ee, func);
+   IFE;
+   ee->func.fn_focus_in = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas focus out events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee loses focus.
+ */
+EAPI void
+ecore_evas_callback_focus_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_focus_out_set");
+       return;
+     }
+   IFC(ee, fn_callback_focus_out_set) (ee, func);
+   IFE;
+   ee->func.fn_focus_out = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas sticky events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee becomes sticky.
+ */
+EAPI void
+ecore_evas_callback_sticky_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_sticky_set");
+       return;
+     }
+   IFC(ee, fn_callback_sticky_set) (ee, func);
+   IFE;
+   ee->func.fn_sticky = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas un-sticky events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee becomes un-sticky.
+ */
+EAPI void
+ecore_evas_callback_unsticky_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_unsticky_set");
+       return;
+     }
+   IFC(ee, fn_callback_unsticky_set) (ee, func);
+   IFE;
+   ee->func.fn_unsticky = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas mouse in events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever the mouse enters @p ee.
+ */
+EAPI void
+ecore_evas_callback_mouse_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_mouse_in_set");
+       return;
+     }
+   IFC(ee, fn_callback_mouse_in_set) (ee, func);
+   IFE;
+   ee->func.fn_mouse_in = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas mouse out events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever the mouse leaves @p ee.
+ */
+EAPI void
+ecore_evas_callback_mouse_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_mouse_out_set");
+       return;
+     }
+   IFC(ee, fn_callback_mouse_out_set) (ee, func);
+   IFE;
+   ee->func.fn_mouse_out = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas mouse pre render events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called just before the evas in @p ee is rendered.
+ */
+EAPI void
+ecore_evas_callback_pre_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_pre_render_set");
+       return;
+     }
+   IFC(ee, fn_callback_pre_render_set) (ee, func);
+   IFE;
+   ee->func.fn_pre_render = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas mouse post render events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called just after the evas in @p ee is rendered.
+ */
+EAPI void
+ecore_evas_callback_post_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_post_render_set");
+       return;
+     }
+   IFC(ee, fn_callback_post_render_set) (ee, func);
+   IFE;
+   ee->func.fn_post_render = func;
+}
+
+/**
+ * Set a callback for Ecore_Evas pre-free event.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+ *
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called just before the instance @p ee is freed.
+ */
+EAPI void
+ecore_evas_callback_pre_free_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_callback_pre_free_set");
+       return;
+     }
+   ee->func.fn_pre_free = func;
+}
+
+/**
+ * Get an Ecore_Evas's Evas
+ * @param ee The Ecore_Evas whose Evas you wish to get
+ * @return The Evas wrapped by @p ee
+ *
+ * This function returns the Evas contained within @p ee.
+ */
+EAPI Evas *
+ecore_evas_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_get");
+       return NULL;
+     }
+   return ee->evas;
+}
+
+/**
+ * Move an Ecore_Evas
+ * @param ee The Ecore_Evas to move
+ * @param x The x coordinate to move to
+ * @param y The y coordinate to move to
+ *
+ * This moves @p ee to the screen coordinates (@p x, @p y)
+ */
+EAPI void
+ecore_evas_move(Ecore_Evas *ee, int x, int y)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_move");
+       return;
+     }
+   if (ee->prop.fullscreen) return;
+   IFC(ee, fn_move) (ee, x, y);
+   IFE;
+}
+
+/**
+ * Provide Managed move co-ordinates for an Ecore_Evas
+ * @param ee The Ecore_Evas to move
+ * @param x The x coordinate to set as the managed location
+ * @param y The y coordinate to set as the managed location
+ *
+ * This sets the managed geometry position of the @p ee to (@p x, @p y)
+ */
+EAPI void
+ecore_evas_managed_move(Ecore_Evas *ee, int x, int y)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_move");
+       return;
+     }
+   IFC(ee, fn_managed_move) (ee, x, y);
+   IFE;
+}
+
+/**
+ * Resize an Ecore_Evas
+ * @param ee The Ecore_Evas to move
+ * @param w The w coordinate to resize to
+ * @param h The h coordinate to resize to
+ *
+ * This resizes @p ee to @p w x @p h
+ */
+EAPI void
+ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_resize");
+       return;
+     }
+   if (ee->prop.fullscreen) return;
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_resize) (ee, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_resize) (ee, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Resize an Ecore_Evas
+ * @param ee The Ecore_Evas to move
+ * @param x The x coordinate to move to
+ * @param y The y coordinate to move to
+ * @param w The w coordinate to resize to
+ * @param h The h coordinate to resize to
+ *
+ * This moves @p ee to the screen coordinates (@p x, @p y) and  resizes
+ * it to @p w x @p h.
+ *
+ */
+EAPI void
+ecore_evas_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_move_resize");
+       return;
+     }
+   if (ee->prop.fullscreen) return;
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_move_resize) (ee, x, y, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_move_resize) (ee, x, y, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Get the geometry of an Ecore_Evas
+ * @param ee The Ecore_Evas whose geometry y
+ * @param x A pointer to an int to place the x coordinate in
+ * @param y A pointer to an int to place the y coordinate in
+ * @param w A pointer to an int to place the w size in
+ * @param h A pointer to an int to place the h size in
+ *
+ * This function takes four pointers to (already allocated) ints, and places
+ * the geometry of @p ee in them.
+ *
+ * @code
+ * int x, y, w, h;
+ * ecore_evas_geometry_get(ee, &x, &y, &w, &h);
+ * @endcode
+ *
+ */
+EAPI void
+ecore_evas_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_geometry_get");
+       return;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       if (x) *x = ee->x;
+       if (y) *y = ee->y;
+       if (w) *w = ee->h;
+       if (h) *h = ee->w;
+     }
+   else
+     {
+       if (x) *x = ee->x;
+       if (y) *y = ee->y;
+       if (w) *w = ee->w;
+       if (h) *h = ee->h;
+     }
+}
+
+/**
+ * Set the rotation of an Ecore_Evas' window
+ *
+ * @param ee The Ecore_Evas
+ * @param rot the angle (in degrees) of rotation.
+ *
+ * The allowed values of @p rot depend on the engine being used. Most only
+ * allow multiples of 90.
+ */
+EAPI void
+ecore_evas_rotation_set(Ecore_Evas *ee, int rot)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_rotation_set");
+       return;
+     }
+   rot = rot % 360;
+   while (rot < 0) rot += 360;
+   while (rot >= 360) rot -= 360;
+   IFC(ee, fn_rotation_set) (ee, rot, 0);
+   /* make sure everything gets redrawn */
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+   IFE;
+}
+
+/**
+ * Set the rotation of an Ecore_Evas' window
+ *
+ * @param ee The Ecore_Evas
+ * @param rot the angle (in degrees) of rotation.
+ *
+ * The allowed values of @p rot depend on the engine being used. Most only
+ * allow multiples of 90.
+ */
+EAPI void
+ecore_evas_rotation_with_resize_set(Ecore_Evas *ee, int rot)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_rotation_set");
+       return;
+     }
+   rot = rot % 360;
+   while (rot < 0) rot += 360;
+   while (rot >= 360) rot -= 360;
+   IFC(ee, fn_rotation_set) (ee, rot, 1);
+   /* make sure everything gets redrawn */
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+   IFE;
+}
+
+/**
+ * Set the rotation of an Ecore_Evas' window
+ *
+ * @param ee The Ecore_Evas
+ * @return the angle (in degrees) of rotation.
+ *
+ */
+EAPI int
+ecore_evas_rotation_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_rotation_get");
+       return 0;
+     }
+   return ee->rotation;
+}
+
+/**
+ * Set whether an Ecore_Evas is shaped or not.
+ * @param ee The Ecore_Evas to shape
+ * @param shaped 1 to shape, 0 to not
+ *
+ * This function allows one to make an Ecore_Evas shaped to the contents of the
+ * evas. If @p shaped is 1, @p ee will be transparent in parts of the evas that
+ * contain no objects. If @p shaped is 0, then @p ee will be rectangular, and
+ * and parts with no data will show random framebuffer artifacting. For
+ * non-shaped Ecore_Evases, it is recommend to cover the entire evas with a
+ * background object.
+ */
+EAPI void
+ecore_evas_shaped_set(Ecore_Evas *ee, int shaped)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_shaped_set");
+       return;
+     }
+   IFC(ee, fn_shaped_set) (ee, shaped);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas is shaped or not.
+ * @param ee The Ecore_Evas to query.
+ * @return 1 if shaped, 0 if not.
+ *
+ * This function returns 1 if @p ee is shaped, and 0 if not.
+ */
+EAPI int
+ecore_evas_shaped_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_shaped_get");
+       return 0;
+     }
+   return ee->shaped ? 1:0;
+}
+
+/**
+ * Set whether an Ecore_Evas has an alpha channel or not.
+ * @param ee The Ecore_Evas to shape
+ * @param alpha 1 to enable the alpha channel, 0 to disable it
+ *
+ * This function allows you to make an Ecore_Evas translucent using an
+ * alpha channel. See ecore_evas_shaped_set() for details. The difference
+ * between a shaped window and a window with an alpha channel is that an
+ * alpha channel supports multiple levels of transpararency, as opposed to
+ * the 1 bit transparency of a shaped window (a pixel is either opaque, or
+ * it's transparent).
+ */
+EAPI void
+ecore_evas_alpha_set(Ecore_Evas *ee, int alpha)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_alpha_set");
+       return;
+     }
+   IFC(ee, fn_alpha_set) (ee, alpha);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas has an alpha channel.
+ * @param ee The Ecore_Evas to query.
+ * @return 1 if ee has an alpha channel, 0 if it does not.
+ *
+ * This function returns 1 if @p ee has an alpha channel, and 0 if
+ * it does not.
+ */
+EAPI int
+ecore_evas_alpha_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_alpha_get");
+       return 0;
+     }
+   return ee->alpha ? 1:0;
+}
+
+/**
+ * Set whether an Ecore_Evas has an transparent window or not.
+ * @param ee The Ecore_Evas to shape
+ * @param transparent 1 to enable the transparent window, 0 to disable it
+ *
+ * This function allows you to make an Ecore_Evas translucent using an
+ * alpha channel. See ecore_evas_shaped_set() for details. The difference
+ * between a shaped window and a window with an alpha channel is that an
+ * alpha channel supports multiple levels of transpararency, as opposed to
+ * the 1 bit transparency of a shaped window (a pixel is either opaque, or
+ * it's transparent).
+ */
+EAPI void
+ecore_evas_transparent_set(Ecore_Evas *ee, int transparent)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_transparent_set");
+       return;
+     }
+   IFC(ee, fn_transparent_set) (ee, transparent);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas has an alpha channel.
+ * @param ee The Ecore_Evas to query.
+ * @return 1 if ee has an alpha channel, 0 if it does not.
+ *
+ * This function returns 1 if @p ee has an alpha channel, and 0 if
+ * it does not.
+ */
+EAPI int
+ecore_evas_transparent_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_transparent_get");
+       return 0;
+     }
+   return ee->transparent ? 1:0;
+}
+
+/**
+ * Show an Ecore_Evas' window
+ * @param ee The Ecore_Evas to show.
+ *
+ * This function makes @p ee visible.
+ */
+EAPI void
+ecore_evas_show(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_show");
+       return;
+     }
+   IFC(ee, fn_show) (ee);
+   IFE;
+}
+
+/**
+ * Hide an Ecore_Evas' window
+ * @param ee The Ecore_Evas to show.
+ *
+ * This function makes @p ee hidden.
+ */
+EAPI void
+ecore_evas_hide(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_hide");
+       return;
+     }
+   IFC(ee, fn_hide) (ee);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is visible or not.
+ * @param ee The Ecore_Evas to query.
+ * @return 1 if visible, 0 if not.
+ *
+ * This function queries @p ee and returns 1 if it is visible, and 0 if not.
+ */
+EAPI int
+ecore_evas_visibility_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_visibility_get");
+       return 0;
+     }
+   return ee->visible ? 1:0;
+}
+
+/**
+ * Raise and Ecore_Evas' window.
+ * @param ee The Ecore_Evas to raise.
+ *
+ * This functions raises the Ecore_Evas to the front.
+ */
+EAPI void
+ecore_evas_raise(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_raise");
+       return;
+     }
+   IFC(ee, fn_raise) (ee);
+   IFE;
+}
+
+/**
+ * Lower an Ecore_Evas' window.
+ * @param ee The Ecore_Evas to raise.
+ *
+ * This functions lowers the Ecore_Evas to the back.
+ */
+EAPI void
+ecore_evas_lower(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_lower");
+       return;
+     }
+   IFC(ee, fn_lower) (ee);
+   IFE;
+}
+
+/**
+ * Activate (set focus to, via the window manager) an Ecore_Evas' window.
+ * @param ee The Ecore_Evas to activate.
+ *
+ * This functions activates the Ecore_Evas.
+ */
+EAPI void
+ecore_evas_activate(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_activate");
+       return;
+     }
+   IFC(ee, fn_activate) (ee);
+   IFE;
+}
+
+/**
+ * Set the title of an Ecore_Evas' window
+ * @param ee The Ecore_Evas whose title you wish to set.
+ * @param t The title
+ *
+ * This function sets the title of @p ee to @p t.
+ */
+EAPI void
+ecore_evas_title_set(Ecore_Evas *ee, const char *t)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_title_set");
+       return;
+     }
+   IFC(ee, fn_title_set) (ee, t);
+   IFE;
+}
+
+/**
+ * Get the title of an Ecore_Evas' window
+ * @param ee The Ecore_Evas whose title you wish to get.
+ * @return The title of @p ee.
+ *
+ * This function returns the title of @p ee.
+ */
+EAPI const char *
+ecore_evas_title_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_title_get");
+       return NULL;
+     }
+   return ee->prop.title;
+}
+
+/**
+ * Set the name and class of an Ecore_Evas' window
+ * @param ee the Ecore_Evas
+ * @param n the name
+ * @param c the class
+ *
+ * This function sets the name of @p ee to @p n, and its class to @p c.
+ */
+EAPI void
+ecore_evas_name_class_set(Ecore_Evas *ee, const char *n, const char *c)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_name_class_set");
+       return;
+     }
+   IFC(ee, fn_name_class_set) (ee, n, c);
+   IFE;
+}
+
+/**
+ * Get the name and class of an Ecore_Evas' window
+ * @p ee The Ecore_Evas to query
+ * @p n A pointer to a string to place the name in.
+ * @p c A pointer to a string to place the class in.
+ *
+ * This function gets puts the name of @p ee into @p n, and its class into
+ * @p c.
+ */
+EAPI void
+ecore_evas_name_class_get(const Ecore_Evas *ee, const char **n, const char **c)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_name_class_get");
+       return;
+     }
+   if (n) *n = ee->prop.name;
+   if (c) *c = ee->prop.clas;
+}
+
+/**
+ * Set the min size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w The minimum width
+ * @param h The minimum height
+ *
+ * This function sets the minimum size of @p ee to @p w x @p h.
+ */
+EAPI void
+ecore_evas_size_min_set(Ecore_Evas *ee, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_min_set");
+       return;
+     }
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_size_min_set) (ee, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_size_min_set) (ee, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Get the min size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w A pointer to an int to place the min width in.
+ * @param h A pointer to an int to place the min height in.
+ *
+ * This function puts the minimum size of @p ee into @p w and @p h.
+ */
+EAPI void
+ecore_evas_size_min_get(const Ecore_Evas *ee, int *w, int *h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_min_get");
+       return;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       if (w) *w = ee->prop.min.h;
+       if (h) *h = ee->prop.min.w;
+     }
+   else
+     {
+       if (w) *w = ee->prop.min.w;
+       if (h) *h = ee->prop.min.h;
+     }
+}
+
+/**
+ * Set the max size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w The maximum width
+ * @param h The maximum height
+ *
+ * This function sets the maximum size of @p ee to @p w x @p h.
+ */
+EAPI void
+ecore_evas_size_max_set(Ecore_Evas *ee, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_max_set");
+       return;
+     }
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_size_max_set) (ee, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_size_max_set) (ee, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Get the max size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w A pointer to an int to place the max width in.
+ * @param h A pointer to an int to place the max height in.
+ *
+ * This function puts the maximum size of @p ee into @p w and @p h.
+ */
+EAPI void
+ecore_evas_size_max_get(const Ecore_Evas *ee, int *w, int *h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_max_get");
+       return;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       if (w) *w = ee->prop.max.h;
+       if (h) *h = ee->prop.max.w;
+     }
+   else
+     {
+       if (w) *w = ee->prop.max.w;
+       if (h) *h = ee->prop.max.h;
+     }
+}
+
+/**
+ * Set the base size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w The base width
+ * @param h The base height
+ *
+ * This function sets the base size of @p ee to @p w x @p h.
+ */
+EAPI void
+ecore_evas_size_base_set(Ecore_Evas *ee, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_base_set");
+       return;
+     }
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_size_base_set) (ee, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_size_base_set) (ee, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Get the base size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w A pointer to an int to place the base width in.
+ * @param h A pointer to an int to place the base height in.
+ *
+ * This function puts the base size of @p ee into @p w and @p h.
+ */
+EAPI void
+ecore_evas_size_base_get(const Ecore_Evas *ee, int *w, int *h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_base_get");
+       return;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       if (w) *w = ee->prop.base.h;
+       if (h) *h = ee->prop.base.w;
+     }
+   else
+     {
+       if (w) *w = ee->prop.base.w;
+       if (h) *h = ee->prop.base.h;
+     }
+}
+
+/**
+ * Set the step size of an Ecore_Evas
+ * @param ee The Ecore_Evas to set
+ * @param w The step width
+ * @param h The step height
+ *
+ * This function sets the step size of @p ee to @p w x @p h. This limits the
+ * size of an Ecore_Evas to always being an integer multiple of the step size.
+ */
+EAPI void
+ecore_evas_size_step_set(Ecore_Evas *ee, int w, int h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_step_set");
+       return;
+     }
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       IFC(ee, fn_size_step_set) (ee, h, w);
+       IFE;
+     }
+   else
+     {
+       IFC(ee, fn_size_step_set) (ee, w, h);
+       IFE;
+     }
+}
+
+/**
+ * Get the step size of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @param w A pointer to an int to place the step width in.
+ * @param h A pointer to an int to place the step height in.
+ *
+ * This function puts the step size of @p ee into @p w and @p h.
+ */
+EAPI void
+ecore_evas_size_step_get(const Ecore_Evas *ee, int *w, int *h)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_size_step_get");
+       return;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       if (w) *w = ee->prop.step.h;
+       if (h) *h = ee->prop.step.w;
+     }
+   else
+     {
+       if (w) *w = ee->prop.step.w;
+       if (h) *h = ee->prop.step.h;
+     }
+}
+
+/**
+ * Set the cursor of an Ecore_Evas
+ * @param ee The Ecore_Evas
+ * @param file  The path to an image file for the cursor
+ * @param layer
+ * @param hot_x The x coordinate of the cursor's hot spot
+ * @param hot_y The y coordinate of the cursor's hot spot
+ *
+ * This function makes the mouse cursor over @p ee be the image specified by
+ * @p file. The actual point within the image that the mouse is at is specified
+ * by @p hot_x and @p hot_y, which are coordinates with respect to the top left
+ * corner of the cursor image.
+ */
+EAPI void
+ecore_evas_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y)
+{
+   Evas_Object  *obj = NULL;
+
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_cursor_set");
+       return;
+     }
+
+   if (file)
+     {
+        int x, y;
+
+        obj = evas_object_image_add(ee->evas);
+        evas_object_image_file_set(obj, file, NULL);
+        evas_object_image_size_get(obj, &x, &y);
+        evas_object_resize(obj, x, y);
+        evas_object_image_fill_set(obj, 0, 0, x, y);
+     }
+
+   IFC(ee, fn_object_cursor_set) (ee, obj, layer, hot_x, hot_y);
+   IFE;
+}
+
+/**
+ * Set the cursor of an Ecore_Evas
+ * @param ee The Ecore_Evas
+ * @param obj The Evas_Object for the cursor
+ * @param layer
+ * @param hot_x The x coordinate of the cursor's hot spot
+ * @param hot_y The y coordinate of the cursor's hot spot
+ *
+ * This function makes the mouse cursor over @p ee be the image specified by
+ * @p file. The actual point within the image that the mouse is at is specified
+ * by @p hot_x and @p hot_y, which are coordinates with respect to the top left
+ * corner of the cursor image.
+ */
+EAPI void
+ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_cursor_set");
+       return;
+     }
+   IFC(ee, fn_object_cursor_set) (ee, obj, layer, hot_x, hot_y);
+   IFE;
+}
+
+/**
+ * Get information about an Ecore_Evas' cursor
+ * @param ee The Ecore_Evas to set
+ * @param obj A pointer to an Evas_Object to place the cursor Evas_Object.
+ * @param layer A pointer to an int to place the cursor's layer in..
+ * @param hot_x A pointer to an int to place the cursor's hot_x coordinate in.
+ * @param hot_y A pointer to an int to place the cursor's hot_y coordinate in.
+ *
+ * This function queries information about an Ecore_Evas' cursor.
+ */
+EAPI void
+ecore_evas_cursor_get(const Ecore_Evas *ee, Evas_Object **obj, int *layer, int *hot_x, int *hot_y)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_cursor_get");
+       return;
+     }
+   if (obj) *obj = ee->prop.cursor.object;
+   if (layer) *layer = ee->prop.cursor.layer;
+   if (hot_x) *hot_x = ee->prop.cursor.hot.x;
+   if (hot_y) *hot_y = ee->prop.cursor.hot.y;
+}
+
+/**
+ * Set the layer of an Ecore_Evas' window
+ * @param ee The Ecore_Evas
+ * @param layer The layer to put @p ee on.
+ *
+ * This function moves @p ee to the layer @p layer.
+ */
+EAPI void
+ecore_evas_layer_set(Ecore_Evas *ee, int layer)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_layer_set");
+       return;
+     }
+   IFC(ee, fn_layer_set) (ee, layer);
+   IFE;
+}
+
+/**
+ * Get the layer of an Ecore_Evas' window
+ * @param ee The Ecore_Evas to set
+ * @return the layer @p ee's window is on.
+ *
+ */
+EAPI int
+ecore_evas_layer_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_layer_get");
+       return 0;
+     }
+   return ee->prop.layer;
+}
+
+/**
+ * Set the focus of an Ecore_Evas' window
+ * @param ee The Ecore_Evas
+ * @param on 1 for focus, 0 to defocus.
+ *
+ * This function focuses @p ee if @p on is 1, or defocuses @p ee if @p on is 0.
+ */
+EAPI void
+ecore_evas_focus_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_focus_set");
+       return;
+     }
+   IFC(ee, fn_focus_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is focused or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee if focused, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_focus_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_focus_get");
+       return 0;
+     }
+   return ee->prop.focused ? 1:0;
+}
+
+/**
+ * Iconify or uniconify an Ecore_Evas' window
+ * @param ee The Ecore_Evas
+ * @param on 1 to iconify, 0 to uniconify.
+ *
+ * This function iconifies @p ee if @p on is 1, or uniconifies @p ee if @p on
+ * is 0.
+ */
+EAPI void
+ecore_evas_iconified_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_iconified_set");
+       return;
+     }
+   IFC(ee, fn_iconified_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is iconified or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee is iconified, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_iconified_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_iconified_get");
+       return 0;
+     }
+   return ee->prop.iconified ? 1:0;
+}
+
+/**
+ * Set whether an Ecore_Evas' window is borderless or not
+ * @param ee The Ecore_Evas
+ * @param on 1 for borderless, 0 for bordered.
+ *
+ * This function makes @p ee borderless if @p on is 1, or bordered if @p on
+ * is 0.
+ */
+EAPI void
+ecore_evas_borderless_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_borderless_set");
+       return;
+     }
+   IFC(ee, fn_borderless_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is borderless or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee is borderless, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_borderless_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_borderless_get");
+       return 0;
+     }
+   return ee->prop.borderless ? 1:0;
+}
+
+/**
+ * Tell the WM whether or not to ignore an Ecore_Evas' window
+ * @param ee The Ecore_Evas
+ * @param on 1 to ignore, 0 to not.
+ *
+ * This function causes the window manager to ignore @p ee if @p on is 1,
+ * or not ignore @p ee if @p on is 0.
+ */
+EAPI void
+ecore_evas_override_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_override_set");
+       return;
+     }
+   IFC(ee, fn_override_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is overridden or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee is overridden, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_override_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_override_get");
+       return 0;
+     }
+   return ee->prop.override ? 1:0;
+}
+
+/**
+ * Maximize (or unmaximize) an Ecore_Evas' window
+ * @param ee The Ecore_Evas
+ * @param on 1 to maximize, 0 to unmaximize.
+ *
+ * This function maximizes @p ee if @p on is 1, or unmaximizes @p ee
+ * if @p on is 0.
+ */
+EAPI void
+ecore_evas_maximized_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_maximized_set");
+       return;
+     }
+   IFC(ee, fn_maximized_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is maximized or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee is maximized, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_maximized_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_maximized_get");
+       return 0;
+     }
+   return ee->prop.maximized ? 1:0;
+}
+
+/**
+ * Set whether or not an Ecore_Evas' window is fullscreen
+ * @param ee The Ecore_Evas
+ * @param on 1 fullscreen, 0 not.
+ *
+ * This function causes @p ee to be fullscreen if @p on is 1,
+ * or not if @p on is 0.
+ */
+EAPI void
+ecore_evas_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_fullscreen_set");
+       return;
+     }
+   IFC(ee, fn_fullscreen_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window is fullscreen or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee is fullscreen, 0 if not.
+ *
+ */
+EAPI int
+ecore_evas_fullscreen_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_fullscreen_get");
+       return 0;
+     }
+   return ee->prop.fullscreen ? 1:0;
+}
+
+/**
+ * Set whether or not an Ecore_Evas' window should avoid damage
+ *
+ * @param ee The Ecore_Evas
+ * @param on 1 to avoid damage, 0 to not
+ *
+ * This function causes @p ee to be drawn to a pixmap to avoid recalculations.
+ * On expose events it will copy from the pixmap to the window.
+ */
+EAPI void
+ecore_evas_avoid_damage_set(Ecore_Evas *ee, Ecore_Evas_Avoid_Damage_Type on)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_avoid_damage_set");
+       return;
+     }
+   IFC(ee, fn_avoid_damage_set) (ee, on);
+   IFE;
+}
+
+/**
+ * Query whether an Ecore_Evas' window avoids damage or not
+ * @param ee The Ecore_Evas to set
+ * @return 1 if @p ee avoids damage, 0 if not.
+ *
+ */
+EAPI Ecore_Evas_Avoid_Damage_Type
+ecore_evas_avoid_damage_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                        "ecore_evas_avoid_damage_get");
+       return 0;
+     }
+   return ee->prop.avoid_damage;
+}
+
+/**
+ * Set the withdrawn state of an Ecore_Evas' window.
+ * @param ee The Ecore_Evas whose window's withdrawn state is set.
+ * @param withdrawn The Ecore_Evas window's new withdrawn state.
+ *
+ */
+EAPI void
+ecore_evas_withdrawn_set(Ecore_Evas *ee, int withdrawn)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_withdrawn_set");
+        return;
+     }
+   
+   IFC(ee, fn_withdrawn_set) (ee, withdrawn);
+   IFE;
+}
+
+/**
+ * Returns the withdrawn state of an Ecore_Evas' window.
+ * @param ee The Ecore_Evas whose window's withdrawn state is returned.
+ * @return The Ecore_Evas window's withdrawn state.
+ *
+ */
+EAPI int
+ecore_evas_withdrawn_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_withdrawn_get");
+        return 0;
+     } else
+     return ee->prop.withdrawn ? 1:0;
+}
+
+/**
+ * Set the sticky state of an Ecore_Evas window.
+ *
+ * @param ee The Ecore_Evas whose window's sticky state is set.
+ * @param sticky The Ecore_Evas window's new sticky state.
+ *
+ */
+EAPI void
+ecore_evas_sticky_set(Ecore_Evas *ee, int sticky)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_sticky_set");
+        return;
+     }
+   
+   IFC(ee, fn_sticky_set) (ee, sticky);
+   IFE;
+}
+
+/**
+ * Returns the sticky state of an Ecore_Evas' window.
+ *
+ * @param ee The Ecore_Evas whose window's sticky state is returned.
+ * @return The Ecore_Evas window's sticky state.
+ *
+ */
+EAPI int
+ecore_evas_sticky_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_sticky_get");
+        return 0;
+     } else
+     return ee->prop.sticky ? 1:0;
+}
+
+/**
+ * Set if this evas should ignore events
+ *
+ * @param ee The Ecore_Evas whose window's to ignore events.
+ * @param ignore The Ecore_Evas new ignore state.
+ *
+ */
+EAPI void
+ecore_evas_ignore_events_set(Ecore_Evas *ee, int ignore)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_ignore_events_set");
+        return;
+     }
+   
+   IFC(ee, fn_ignore_events_set) (ee, ignore);
+   IFE;
+}
+
+/**
+ * Returns the ignore state of an Ecore_Evas' window.
+ *
+ * @param ee The Ecore_Evas whose window's ignore events state is returned.
+ * @return The Ecore_Evas window's ignore state.
+ *
+ */
+EAPI int
+ecore_evas_ignore_events_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_ignore_events_get");
+        return 0;
+     }
+   return ee->ignore_events ? 1 : 0;
+}
+
+EAPI void
+ecore_evas_manual_render_set(Ecore_Evas *ee, int manual_render)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_manual_render_set");
+        return;
+     }
+   ee->manual_render = manual_render;
+}
+
+EAPI int
+ecore_evas_manual_render_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_manual_render_get");
+        return 0;
+     }
+   return ee->manual_render ? 1 : 0;
+}
+
+EAPI void
+ecore_evas_manual_render(Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_manual_render");
+        return;
+     }
+   if (ee->engine.func->fn_render)
+     ee->engine.func->fn_render(ee);
+}
+
+EAPI void
+ecore_evas_comp_sync_set(Ecore_Evas *ee, int do_sync)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_comp_sync_set");
+        return;
+     }
+   ee->no_comp_sync = !do_sync;
+}
+
+EAPI int
+ecore_evas_comp_sync_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+     {
+        ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+                         "ecore_evas_comp_sync_get");
+        return 0;
+     }
+   return !ee->no_comp_sync;
+}
+
+EAPI Ecore_Window
+ecore_evas_window_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+   {
+      ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
+         "ecore_evas_window_get");
+      return 0;
+   }
+
+   return ee->prop.window;
+}
+
+/* fps debug calls - for debugging how much time your app actually spends */
+/* rendering graphics... :) */
+
+static int _ecore_evas_fps_debug_init_count = 0;
+static int _ecore_evas_fps_debug_fd = -1;
+unsigned int *_ecore_evas_fps_rendertime_mmap = NULL;
+
+void
+_ecore_evas_fps_debug_init(void)
+{
+   char buf[4096];
+
+   _ecore_evas_fps_debug_init_count++;
+   if (_ecore_evas_fps_debug_init_count > 1) return;
+   snprintf(buf, sizeof(buf), "/tmp/.ecore_evas_fps_debug-%i", (int)getpid());
+   _ecore_evas_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
+   if (_ecore_evas_fps_debug_fd < 0)
+     {
+       unlink(buf);
+       _ecore_evas_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
+     }
+   if (_ecore_evas_fps_debug_fd >= 0)
+     {
+       unsigned int zero = 0;
+       char *buf = (char *)&zero;
+       ssize_t todo = sizeof(unsigned int);
+
+       while (todo > 0)
+         {
+            ssize_t r = write(_ecore_evas_fps_debug_fd, buf, todo);
+            if (r > 0)
+              {
+                 todo -= r;
+                 buf += r;
+              }
+            else if ((r < 0) && (errno == EINTR))
+              continue;
+            else
+              {
+                 ERR("could not write to file '%s' fd %d: %s",
+                     buf, _ecore_evas_fps_debug_fd, strerror(errno));
+                 close(_ecore_evas_fps_debug_fd);
+                 _ecore_evas_fps_debug_fd = -1;
+                 return;
+              }
+         }
+       _ecore_evas_fps_rendertime_mmap = mmap(NULL, sizeof(unsigned int),
+                                              PROT_READ | PROT_WRITE,
+                                              MAP_SHARED,
+                                              _ecore_evas_fps_debug_fd, 0);
+       if (_ecore_evas_fps_rendertime_mmap == MAP_FAILED)
+         _ecore_evas_fps_rendertime_mmap = NULL;
+     }
+}
+
+void
+_ecore_evas_fps_debug_shutdown(void)
+{
+   _ecore_evas_fps_debug_init_count--;
+   if (_ecore_evas_fps_debug_init_count > 0) return;
+   if (_ecore_evas_fps_debug_fd >= 0)
+     {
+       char buf[4096];
+
+       snprintf(buf, sizeof(buf), "/tmp/.ecore_evas_fps_debug-%i", (int)getpid());
+       unlink(buf);
+       if (_ecore_evas_fps_rendertime_mmap)
+         {
+            munmap(_ecore_evas_fps_rendertime_mmap, sizeof(int));
+            _ecore_evas_fps_rendertime_mmap = NULL;
+         }
+       close(_ecore_evas_fps_debug_fd);
+       _ecore_evas_fps_debug_fd = -1;
+     }
+}
+
+void
+_ecore_evas_fps_debug_rendertime_add(double t)
+{
+   static double rtime = 0.0;
+   static double rlapse = 0.0;
+   static int frames = 0;
+   static int flapse = 0;
+   double tim;
+
+   tim = ecore_time_get();
+   rtime += t;
+   frames++;
+   if (rlapse == 0.0)
+     {
+        rlapse = tim;
+        flapse = frames;
+     }
+   else if ((tim - rlapse) >= 0.5)
+     {
+        printf("FRAME: %i, FPS: %3.1f, RTIME %3.0f%%\n",
+               frames,
+               (frames - flapse) / (tim - rlapse),
+               (100.0 * rtime) / (tim - rlapse)
+               );
+        rlapse = tim;
+        flapse = frames;
+        rtime = 0.0;
+     }
+}
+
+void
+_ecore_evas_register(Ecore_Evas *ee)
+{
+   ee->registered = 1;
+   ecore_evases = (Ecore_Evas *)eina_inlist_prepend
+     (EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
+}
+
+void
+_ecore_evas_free(Ecore_Evas *ee)
+{
+   if (ee->func.fn_pre_free) ee->func.fn_pre_free(ee);
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_NONE);
+   while (ee->sub_ecore_evas)
+     {
+       _ecore_evas_free(ee->sub_ecore_evas->data);
+     }
+   if (ee->data) eina_hash_free(ee->data);
+   if (ee->name) free(ee->name);
+   if (ee->prop.title) free(ee->prop.title);
+   if (ee->prop.name) free(ee->prop.name);
+   if (ee->prop.clas) free(ee->prop.clas);
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+   if (ee->evas) evas_free(ee->evas);
+   ee->data = NULL;
+   ee->driver = NULL;
+   ee->name = NULL;
+   ee->prop.title = NULL;
+   ee->prop.name = NULL;
+   ee->prop.clas = NULL;
+   ee->prop.cursor.object = NULL;
+   ee->evas = NULL;
+   if (ee->engine.idle_flush_timer)
+     ecore_timer_del(ee->engine.idle_flush_timer);
+   if (ee->engine.func->fn_free) ee->engine.func->fn_free(ee);
+   if (ee->registered)
+     {
+        ecore_evases = (Ecore_Evas *)eina_inlist_remove
+          (EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
+     }
+   free(ee);
+}
+
+static int
+_ecore_evas_cb_idle_flush(void *data)
+{
+   Ecore_Evas *ee;
+
+   ee = (Ecore_Evas *)data;
+   evas_render_idle_flush(ee->evas);
+   ee->engine.idle_flush_timer = NULL;
+   return 0;
+}
+
+static int
+_ecore_evas_async_events_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   evas_async_events_process();
+
+   return 1;
+}
+
+void
+_ecore_evas_idle_timeout_update(Ecore_Evas *ee)
+{
+   if (ee->engine.idle_flush_timer)
+     ecore_timer_del(ee->engine.idle_flush_timer);
+   ee->engine.idle_flush_timer = ecore_timer_add(IDLE_FLUSH_TIME,
+                                                _ecore_evas_cb_idle_flush,
+                                                ee);
+}
+
+void
+_ecore_evas_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int timestamp)
+{
+   ee->mouse.x = x;
+   ee->mouse.y = y;
+   if (ee->prop.cursor.object)
+     {
+       evas_object_show(ee->prop.cursor.object);
+       if (ee->rotation == 0)
+         evas_object_move(ee->prop.cursor.object,
+                          x - ee->prop.cursor.hot.x,
+                          y - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 90)
+         evas_object_move(ee->prop.cursor.object,
+                          ee->h - y - 1 - ee->prop.cursor.hot.x,
+                          x - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 180)
+         evas_object_move(ee->prop.cursor.object,
+                          ee->w - x - 1 - ee->prop.cursor.hot.x,
+                          ee->h - y - 1 - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 270)
+         evas_object_move(ee->prop.cursor.object,
+                          y - ee->prop.cursor.hot.x,
+                          ee->w - x - 1 - ee->prop.cursor.hot.y);
+     }
+   if (ee->rotation == 0)
+     evas_event_feed_mouse_move(ee->evas, x, y, timestamp, NULL);
+   else if (ee->rotation == 90)
+     evas_event_feed_mouse_move(ee->evas, ee->h - y - 1, x, timestamp, NULL);
+   else if (ee->rotation == 180)
+     evas_event_feed_mouse_move(ee->evas, ee->w - x - 1, ee->h - y - 1, timestamp, NULL);
+   else if (ee->rotation == 270)
+     evas_event_feed_mouse_move(ee->evas, y, ee->w - x - 1, timestamp, NULL);
+}
+
diff --git a/src/lib/ecore_evas/ecore_evas_buffer.c b/src/lib/ecore_evas/ecore_evas_buffer.c
new file mode 100644 (file)
index 0000000..0e194a4
--- /dev/null
@@ -0,0 +1,712 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#include <Ecore_Input.h>
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+static int _ecore_evas_init_count = 0;
+
+static int
+_ecore_evas_buffer_init(void)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+   return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_buffer_free(Ecore_Evas *ee)
+{
+   if (ee->engine.buffer.image)
+     {
+       Ecore_Evas *ee2;
+
+       ee2 = evas_object_data_get(ee->engine.buffer.image, "Ecore_Evas_Parent");
+       evas_object_del(ee->engine.buffer.image);
+       ee2->sub_ecore_evas = eina_list_remove(ee2->sub_ecore_evas, ee);
+     }
+   else
+     {
+       free(ee->engine.buffer.pixels);
+     }
+   _ecore_evas_buffer_shutdown();
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   Evas_Engine_Info_Buffer *einfo;
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (ee->engine.buffer.image)
+     {
+       ee->engine.buffer.pixels = evas_object_image_data_get(ee->engine.buffer.image, 1);
+     }
+   else
+     {
+       if (ee->engine.buffer.pixels) free(ee->engine.buffer.pixels);
+       ee->engine.buffer.pixels = malloc(ee->w * ee->h * sizeof(int));
+     }
+
+   einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
+       einfo->info.dest_buffer = ee->engine.buffer.pixels;
+       einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int);
+       einfo->info.use_color_key = 0;
+       einfo->info.alpha_threshold = 0;
+       einfo->info.func.new_update_region = NULL;
+       einfo->info.func.free_update_region = NULL;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+int
+_ecore_evas_buffer_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+     }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+int
+_ecore_evas_buffer_render(Ecore_Evas *ee)
+{
+   Eina_List *updates, *l, *ll;
+   Ecore_Evas *ee2;
+   int rend = 0;
+
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+       if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+       rend |= _ecore_evas_buffer_render(ee2);
+       if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+   if (ee->engine.buffer.image)
+     {
+       int w, h;
+
+       evas_object_image_size_get(ee->engine.buffer.image, &w, &h);
+       if ((w != ee->w) || (h != ee->h))
+         _ecore_evas_resize(ee, w, h);
+     }
+   updates = evas_render_updates(ee->evas);
+   if (ee->engine.buffer.image)
+     {
+        Eina_Rectangle *r;
+
+       EINA_LIST_FOREACH(updates, l, r)
+         if (ee->engine.buffer.image)
+           evas_object_image_data_update_add(ee->engine.buffer.image,
+                                             r->x, r->y, r->w, r->h);
+     }
+   if (updates)
+     {
+       evas_render_updates_free(updates);
+       _ecore_evas_idle_timeout_update(ee);
+     }
+
+   return updates ? 1 : rend;
+}
+
+static void
+_ecore_evas_buffer_coord_translate(Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
+{
+   Evas_Coord xx, yy, fx, fy, fw, fh;
+
+   evas_object_geometry_get(ee->engine.buffer.image, &xx, &yy, NULL, NULL);
+   evas_object_image_fill_get(ee->engine.buffer.image, &fx, &fy, &fw, &fh);
+
+   if (fw < 1) fw = 1;
+   xx = (*x - xx) - fx;
+   while (xx < 0) xx += fw;
+   while (xx > fw) xx -= fw;
+   *x = (ee->w * xx) / fw;
+
+   if (fh < 1) fh = 1;
+   yy = (*y - yy) - fy;
+   while (yy < 0) yy += fh;
+   while (yy > fh) yy -= fh;
+   *y = (ee->h * yy) / fh;
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_In *ev;
+
+   ee = data;
+   ev = event_info;
+   evas_event_feed_mouse_in(ee->evas, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Out *ev;
+
+   ee = data;
+   ev = event_info;
+   evas_event_feed_mouse_out(ee->evas, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Down *ev;
+
+   ee = data;
+   ev = event_info;
+   evas_event_feed_mouse_down(ee->evas, ev->button, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Up *ev;
+
+   ee = data;
+   ev = event_info;
+   evas_event_feed_mouse_up(ee->evas, ev->button, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Move *ev;
+   Evas_Coord x, y;
+
+   ee = data;
+   ev = event_info;
+   x = ev->cur.canvas.x;
+   y = ev->cur.canvas.y;
+   _ecore_evas_buffer_coord_translate(ee, &x, &y);
+   _ecore_evas_mouse_move_process(ee, x, y, ev->timestamp);
+}
+
+static void
+_ecore_evas_buffer_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Wheel *ev;
+
+   ee = data;
+   ev = event_info;
+   evas_event_feed_mouse_wheel(ee->evas, ev->direction, ev->z, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_multi_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Down *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->canvas.x;
+   y = ev->canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_buffer_coord_translate(ee, &x, &y);
+   xf = (ev->canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->canvas.ysub - (double)yy) + (double)y;
+   evas_event_feed_multi_down(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Up *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->canvas.x;
+   y = ev->canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_buffer_coord_translate(ee, &x, &y);
+   xf = (ev->canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->canvas.ysub - (double)yy) + (double)y;
+   evas_event_feed_multi_up(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_multi_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Move *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->cur.canvas.x;
+   y = ev->cur.canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_buffer_coord_translate(ee, &x, &y);
+   xf = (ev->cur.canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->cur.canvas.ysub - (double)yy) + (double)y;
+   evas_event_feed_multi_move(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_free(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee->driver) _ecore_evas_free(ee);
+}
+
+static void
+_ecore_evas_buffer_cb_key_down(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Key_Down *ev;
+
+   ee = data;
+   ev = event_info;
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Shift"))
+     evas_key_modifier_on(e, "Shift");
+   else
+     evas_key_modifier_off(e, "Shift");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Control"))
+     evas_key_modifier_on(e, "Control");
+   else
+     evas_key_modifier_off(e, "Control");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Alt"))
+     evas_key_modifier_on(e, "Alt");
+   else
+     evas_key_modifier_off(e, "Alt");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Meta"))
+     evas_key_modifier_on(e, "Meta");
+   else
+     evas_key_modifier_off(e, "Meta");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Hyper"))
+     evas_key_modifier_on(e, "Hyper");
+   else
+     evas_key_modifier_off(e, "Hyper");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Super"))
+     evas_key_modifier_on(e, "Super");
+   else
+     evas_key_modifier_off(e, "Super");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Scroll_Lock"))
+     evas_key_lock_on(e, "Scroll_Lock");
+   else
+     evas_key_lock_off(e, "Scroll_Lock");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Num_Lock"))
+     evas_key_lock_on(e, "Num_Lock");
+   else
+     evas_key_lock_off(e, "Num_Lock");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Caps_Lock"))
+     evas_key_lock_on(e, "Caps_Lock");
+   else
+     evas_key_lock_off(e, "Caps_Lock");
+   evas_event_feed_key_down(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_key_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Key_Up *ev;
+
+   ee = data;
+   ev = event_info;
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Shift"))
+     evas_key_modifier_on(e, "Shift");
+   else
+     evas_key_modifier_off(e, "Shift");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Control"))
+     evas_key_modifier_on(e, "Control");
+   else
+     evas_key_modifier_off(e, "Control");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Alt"))
+     evas_key_modifier_on(e, "Alt");
+   else
+     evas_key_modifier_off(e, "Alt");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Meta"))
+     evas_key_modifier_on(e, "Meta");
+   else
+     evas_key_modifier_off(e, "Meta");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Hyper"))
+     evas_key_modifier_on(e, "Hyper");
+   else
+     evas_key_modifier_off(e, "Hyper");
+   if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Super"))
+     evas_key_modifier_on(e, "Super");
+   else
+     evas_key_modifier_off(e, "Super");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Scroll_Lock"))
+     evas_key_lock_on(e, "Scroll_Lock");
+   else
+     evas_key_lock_off(e, "Scroll_Lock");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Num_Lock"))
+     evas_key_lock_on(e, "Num_Lock");
+   else
+     evas_key_lock_off(e, "Num_Lock");
+   if (evas_key_lock_is_set(evas_key_lock_get(e), "Caps_Lock"))
+     evas_key_lock_on(e, "Caps_Lock");
+   else
+     evas_key_lock_off(e, "Caps_Lock");
+   evas_event_feed_key_up(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_buffer_cb_focus_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.focused = 1;
+   evas_focus_in(ee->evas);
+   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+}
+
+static void
+_ecore_evas_buffer_cb_focus_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.focused = 0;
+   evas_focus_out(ee->evas);
+   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+}
+
+static void
+_ecore_evas_buffer_cb_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->visible = 1;
+   if (ee->func.fn_show) ee->func.fn_show(ee);
+}
+
+static void
+_ecore_evas_buffer_cb_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->visible = 0;
+   if (ee->func.fn_hide) ee->func.fn_hide(ee);
+}
+
+static Ecore_Evas_Engine_Func _ecore_buffer_engine_func =
+{
+   _ecore_evas_buffer_free,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_resize,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL, //transparent
+     
+     NULL // render
+};
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI Ecore_Evas *
+ecore_evas_buffer_new(int w, int h)
+{
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Evas_Engine_Info_Buffer *einfo;
+   Ecore_Evas *ee;
+   int rmethod;
+
+   rmethod = evas_render_method_lookup("buffer");
+   if (!rmethod) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_buffer_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_buffer_engine_func;
+
+   ee->driver = "buffer";
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->rotation = 0;
+   ee->visible = 1;
+   ee->w = w;
+   ee->h = h;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = 1;
+   ee->prop.borderless = 1;
+   ee->prop.override = 1;
+   ee->prop.maximized = 1;
+   ee->prop.fullscreen = 0;
+   ee->prop.withdrawn = 0;
+   ee->prop.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   ee->engine.buffer.pixels = malloc(w * h * sizeof(int));
+
+   einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
+       einfo->info.dest_buffer = ee->engine.buffer.pixels;
+       einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int);
+       einfo->info.use_color_key = 0;
+       einfo->info.alpha_threshold = 0;
+       einfo->info.func.new_update_region = NULL;
+       einfo->info.func.free_update_region = NULL;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   evas_key_modifier_add(ee->evas, "Shift");
+   evas_key_modifier_add(ee->evas, "Control");
+   evas_key_modifier_add(ee->evas, "Alt");
+   evas_key_modifier_add(ee->evas, "Meta");
+   evas_key_modifier_add(ee->evas, "Hyper");
+   evas_key_modifier_add(ee->evas, "Super");
+   evas_key_lock_add(ee->evas, "Caps_Lock");
+   evas_key_lock_add(ee->evas, "Num_Lock");
+   evas_key_lock_add(ee->evas, "Scroll_Lock");
+
+   evas_event_feed_mouse_in(ee->evas, 0, NULL);
+
+   ee->engine.func->fn_render = _ecore_evas_buffer_render;
+   _ecore_evas_register(ee);
+   
+   return ee;
+#else
+   return NULL;
+#endif
+}
+
+EAPI const void *
+ecore_evas_buffer_pixels_get(Ecore_Evas *ee)
+{
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   _ecore_evas_buffer_render(ee);
+   return ee->engine.buffer.pixels;
+#else
+   return NULL;
+#endif
+}
+
+EAPI Evas_Object *
+ecore_evas_object_image_new(Ecore_Evas *ee_target)
+{
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Evas_Object *o;
+   Evas_Engine_Info_Buffer *einfo;
+   Ecore_Evas *ee;
+   int rmethod;
+   int w, h;
+
+   rmethod = evas_render_method_lookup("buffer");
+   if (!rmethod) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   o = evas_object_image_add(ee_target->evas);
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_buffer_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_buffer_engine_func;
+
+   ee->driver = "buffer";
+
+   w = 1;
+   h = 1;
+   ee->rotation = 0;
+   ee->visible = 0;
+   ee->w = w;
+   ee->h = h;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = 0;
+   ee->prop.borderless = 1;
+   ee->prop.override = 1;
+   ee->prop.maximized = 0;
+   ee->prop.fullscreen = 0;
+   ee->prop.withdrawn = 0;
+   ee->prop.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   ee->engine.buffer.image = o;
+   evas_object_data_set(ee->engine.buffer.image, "Ecore_Evas", ee);
+   evas_object_data_set(ee->engine.buffer.image, "Ecore_Evas_Parent", ee_target);
+   evas_object_image_size_set(o, ee->w, ee->h);
+   evas_object_image_alpha_set(o, 1);
+   ee->engine.buffer.pixels = evas_object_image_data_get(o, 1);
+   evas_object_image_data_set(o, ee->engine.buffer.pixels);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_IN,
+                                 _ecore_evas_buffer_cb_mouse_in, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_OUT,
+                                 _ecore_evas_buffer_cb_mouse_out, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_DOWN,
+                                 _ecore_evas_buffer_cb_mouse_down, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_UP,
+                                 _ecore_evas_buffer_cb_mouse_up, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_MOVE,
+                                 _ecore_evas_buffer_cb_mouse_move, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MOUSE_WHEEL,
+                                 _ecore_evas_buffer_cb_mouse_wheel, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MULTI_DOWN,
+                                 _ecore_evas_buffer_cb_multi_down, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MULTI_UP,
+                                 _ecore_evas_buffer_cb_multi_up, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_MULTI_MOVE,
+                                 _ecore_evas_buffer_cb_multi_move, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_FREE,
+                                 _ecore_evas_buffer_cb_free, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_KEY_DOWN,
+                                 _ecore_evas_buffer_cb_key_down, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_KEY_UP,
+                                 _ecore_evas_buffer_cb_key_up, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_FOCUS_IN,
+                                 _ecore_evas_buffer_cb_focus_in, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_FOCUS_OUT,
+                                 _ecore_evas_buffer_cb_focus_out, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_SHOW,
+                                 _ecore_evas_buffer_cb_show, ee);
+   evas_object_event_callback_add(ee->engine.buffer.image,
+                                 EVAS_CALLBACK_HIDE,
+                                 _ecore_evas_buffer_cb_hide, ee);
+   einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
+       einfo->info.dest_buffer = ee->engine.buffer.pixels;
+       einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int);
+       einfo->info.use_color_key = 0;
+       einfo->info.alpha_threshold = 0;
+       einfo->info.func.new_update_region = NULL;
+       einfo->info.func.free_update_region = NULL;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   evas_key_modifier_add(ee->evas, "Shift");
+   evas_key_modifier_add(ee->evas, "Control");
+   evas_key_modifier_add(ee->evas, "Alt");
+   evas_key_modifier_add(ee->evas, "Meta");
+   evas_key_modifier_add(ee->evas, "Hyper");
+   evas_key_modifier_add(ee->evas, "Super");
+   evas_key_lock_add(ee->evas, "Caps_Lock");
+   evas_key_lock_add(ee->evas, "Num_Lock");
+   evas_key_lock_add(ee->evas, "Scroll_Lock");
+
+   ee_target->sub_ecore_evas = eina_list_append(ee_target->sub_ecore_evas, ee);
+   
+   ee->engine.func->fn_render = _ecore_evas_buffer_render;
+   
+   return o;
+#else
+   return NULL;
+#endif
+}
diff --git a/src/lib/ecore_evas/ecore_evas_cocoa.c b/src/lib/ecore_evas/ecore_evas_cocoa.c
new file mode 100644 (file)
index 0000000..f1b3445
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_COCOA
+#import <Cocoa/Cocoa.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Input.h"
+#include "Ecore_Input_Evas.h"
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_COCOA
+#include "Ecore_Cocoa.h"
+#include "Evas_Engine_Quartz.h"
+
+// FIXME: this engine has lots of problems. only 1 window at a time, drawRect looks wrong, doesnt handle resizes and more
+
+static int                      _ecore_evas_init_count = 0;
+static Ecore_Evas               *ecore_evases = NULL;
+static Ecore_Event_Handler      *ecore_evas_event_handlers[4] = {
+   NULL, NULL, NULL, NULL
+};
+static Ecore_Idle_Enterer       *ecore_evas_idle_enterer = NULL;
+static Ecore_Poller             *ecore_evas_event = NULL;
+
+static const char               *ecore_evas_cocoa_default = "EFL Cocoa";
+
+@interface EvasView : NSView
+{
+       CGContextRef ctx;
+}
+@end
+
+static EvasView * evas_view;
+static NSWindow * main_window;
+
+@implementation EvasView
+
+- (id) init
+{
+   self = [super init];
+   if (self != nil)
+   {
+      ctx = NULL;
+   }
+   return self;
+}
+
+- (void)drawRect:(NSRect)rect
+{
+   if(ctx != NULL)
+   {
+      Ecore_Evas  *ee;
+
+      EINA_INLIST_FOREACH(ecore_evases, ee)
+      {
+         if (ee->visible)
+            evas_damage_rectangle_add(ee->evas, 0, 0, 400, 400);
+      }
+      return;
+   }
+
+   ctx = [[NSGraphicsContext currentContext] graphicsPort];
+   CGContextRetain(ctx);
+}
+
+- (CGContextRef)context
+{
+   return ctx;
+}
+
+@end
+
+static Ecore_Evas *
+_ecore_evas_cocoa_match(void)
+{
+   return ecore_evases;
+}
+
+static int
+_ecore_evas_cocoa_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                   *ee;
+
+   ee = _ecore_evas_cocoa_match();
+
+   if (!ee) return 1;
+   ee->prop.focused = 1;
+
+   return 0;
+}
+
+static int
+_ecore_evas_cocoa_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                   *ee;
+
+   ee = _ecore_evas_cocoa_match();
+
+   if (!ee) return 1;
+   ee->prop.focused = 0;
+
+   return 0;
+}
+
+static int
+_ecore_evas_cocoa_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   /*Ecore_Cocoa_Event_Video_Resize *e;
+   Ecore_Evas                   *ee;
+
+   e = event;
+   ee = _ecore_evas_cocoa_match();
+
+   if (!ee) return 1; // pass on event
+   evas_output_size_set(ee->evas, e->w, e->h);
+
+   return 0;*/
+}
+
+static int
+_ecore_evas_cocoa_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+   Ecore_Evas                   *ee;
+   int                          w;
+   int                          h;
+
+   ee = _ecore_evas_cocoa_match();
+
+   if (!ee) return 1;
+   evas_output_size_get(ee->evas, &w, &h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
+
+   return 0;
+}
+
+static int
+_ecore_evas_idle_enter(void *data __UNUSED__)
+{
+   Ecore_Evas  *ee;
+   double       t1 = 0.;
+   double       t2 = 0.;
+
+   EINA_INLIST_FOREACH(ecore_evases, ee)
+   {
+      if (ee->visible)
+         evas_render(ee->evas);
+      else
+         evas_norender(ee->evas);
+   }
+
+   return 1;
+}
+
+static int
+_ecore_evas_cocoa_event(void *data)
+{
+   ecore_cocoa_feed_events();
+
+   return 1;
+}
+
+static int
+_ecore_evas_cocoa_init(int w, int h)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+
+   ecore_event_evas_init();
+
+   ecore_evas_idle_enterer = ecore_idle_enterer_add(_ecore_evas_idle_enter, NULL);
+   ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, ecore_evas_event, NULL);
+   ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
+
+   ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_COCOA_EVENT_GOT_FOCUS, _ecore_evas_cocoa_event_got_focus, NULL);
+   ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_COCOA_EVENT_LOST_FOCUS, _ecore_evas_cocoa_event_lost_focus, NULL);
+   ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_COCOA_EVENT_RESIZE, _ecore_evas_cocoa_event_video_resize, NULL);
+   ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_COCOA_EVENT_EXPOSE, _ecore_evas_cocoa_event_video_expose, NULL);
+
+   return _ecore_evas_init_count;
+}
+
+static int
+_ecore_evas_cocoa_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+   {
+      int i;
+
+      while (ecore_evases) _ecore_evas_free(ecore_evases);
+
+      for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
+         ecore_event_handler_del(ecore_evas_event_handlers[i]);
+      ecore_event_evas_shutdown();
+      ecore_idle_enterer_del(ecore_evas_idle_enterer);
+      ecore_evas_idle_enterer = NULL;
+      ecore_poller_del(ecore_evas_event);
+      ecore_evas_event = NULL;
+
+      ecore_event_evas_shutdown();
+   }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_cocoa_free(Ecore_Evas *ee)
+{
+   ecore_evases = (Ecore_Evas *) eina_inlist_remove(EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
+   ecore_event_window_unregister(0);
+   _ecore_evas_cocoa_shutdown();
+   ecore_cocoa_shutdown();
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_object_cursor_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee)
+     ee->prop.cursor.object = NULL;
+}
+
+static void
+_ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+   {
+      ee->prop.cursor.object = NULL;
+      ee->prop.cursor.layer = 0;
+      ee->prop.cursor.hot.x = 0;
+      ee->prop.cursor.hot.y = 0;
+      return;
+   }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                    x - ee->prop.cursor.hot.x,
+                    y - ee->prop.cursor.hot.y);
+
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+
+   if (evas_pointer_inside_get(ee->evas))
+      evas_object_show(ee->prop.cursor.object);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+}
+
+static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
+{
+   _ecore_evas_cocoa_free,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_resize,
+   _ecore_evas_move_resize,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_object_cursor_set,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL, //transparent
+     
+     NULL // render
+};
+#endif
+
+EAPI Ecore_Evas *
+ecore_evas_cocoa_new(const char* name, int w, int h)
+{
+#ifdef BUILD_ECORE_EVAS_COCOA
+   Evas_Engine_Info_Quartz *einfo;
+   Ecore_Evas           *ee;
+   int                  rmethod;
+
+   if (!name)
+     name = ecore_evas_cocoa_default;
+
+   rmethod = evas_render_method_lookup("quartz");
+   if (!rmethod) return NULL;
+
+   if (!ecore_cocoa_init(name)) return NULL;
+
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee)
+     goto shutdown_ecore_cocoa;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_cocoa_init(w, h);
+
+   ecore_event_window_register(0, ee, ee->evas, _ecore_evas_mouse_move_process);
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_cocoa_engine_func;
+
+   ee->driver = "quartz";
+   if (name) ee->name = strdup(name);
+   if (!ee->name)
+     goto free_ee;
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->visible = 1;
+   ee->w = w;
+   ee->h = h;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = 1;
+   ee->prop.borderless = 1;
+   ee->prop.override = 1;
+   ee->prop.maximized = 1;
+   ee->prop.withdrawn = 0;
+   ee->prop.sticky = 0;
+
+   // init evas here
+   ee->evas = evas_new();
+   if (!ee->evas)
+     goto free_name;
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+
+   // Set up the Cocoa runtime
+   [[NSAutoreleasePool alloc] init];
+   [NSApplication sharedApplication];
+
+   // Register ourselves as a full-fledged Cocoa app, instead of a NSUIElement.
+   // This gives benefits like window focus and a dock icon!
+   ProcessSerialNumber psn = { 0, kCurrentProcess };
+   TransformProcessType (&psn, kProcessTransformToForegroundApplication);
+
+   [NSApp finishLaunching];
+
+   // Create our main window, and embed an EvasView in it
+   main_window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,w,h) styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask) backing:NSBackingStoreBuffered defer:NO screen:nil];
+   /* FIXME: manage the case where main_window is NULL witht a goto free_evas; */
+   [main_window makeKeyAndOrderFront:NSApp];
+   [main_window setTitle:[NSString stringWithUTF8String:name]];
+   [main_window makeMainWindow];
+   [main_window setAcceptsMouseMovedEvents:YES];
+   [NSApp activateIgnoringOtherApps:YES];
+
+   evas_view = [[EvasView alloc] initWithFrame:NSMakeRect(0,0,w,h)];
+   [[main_window contentView] addSubview:evas_view];
+
+   // drawRect: must be run at least once, to make sure we've set ctx
+   [evas_view display];
+
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   einfo = (Evas_Engine_Info_Quartz*) evas_engine_info_get(ee->evas);
+   if (!einfo)
+     goto free_window;
+
+   einfo->info.context = [[evas_view context] retain];
+   evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+
+   ecore_evases = (Ecore_Evas *) eina_inlist_prepend(EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
+
+   evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   evas_focus_in(ee->evas);
+
+   return ee;
+
+ free_window:
+   /* FIXME: free window here */
+ free_evas:
+   free(ee->evas);
+ free_name:
+   free(ee->name);
+ free_ee:
+   _ecore_evas_cocoa_shutdown();
+   free(ee);
+ shutdown_ecore_cocoa:
+   ecore_cocoa_shutdown();
+
+   return NULL;
+#else
+   ERR("OUTCH name='%s' size=%dx%d!", name ? name : "", w, h);
+   return NULL;
+#endif
+}
diff --git a/src/lib/ecore_evas/ecore_evas_directfb.c b/src/lib/ecore_evas/ecore_evas_directfb.c
new file mode 100644 (file)
index 0000000..46e81c9
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+#include <Ecore_DirectFB.h>
+#endif
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+static int _ecore_evas_init_count = 0;
+static Ecore_Event_Handler *ecore_evas_event_handlers[13];
+
+static Eina_Hash *ecore_evases_hash = NULL;
+
+static int
+_ecore_evas_directfb_render(Ecore_Evas *ee)
+{
+   Eina_List *updates, *ll;
+   Ecore_Evas *ee2;
+   int rend = 0;
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+       if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+       rend |= _ecore_evas_buffer_render(ee2);
+       if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+#endif
+   if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+   updates = evas_render_updates(ee->evas);
+   if (updates)
+     {
+       evas_render_updates_free(updates);
+       _ecore_evas_idle_timeout_update(ee);
+     }
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+
+   return updates ? 1 : rend;
+}
+
+static char *
+_ecore_evas_directfb_winid_str_get(Ecore_X_Window win)
+{
+   const char *vals = "qWeRtYuIoP5$&<~";
+   static char id[9];
+   unsigned int val;
+   val = (unsigned int)win;
+   id[0] = vals[(val >> 28) & 0xf];
+   id[1] = vals[(val >> 24) & 0xf];
+   id[2] = vals[(val >> 20) & 0xf];
+   id[3] = vals[(val >> 16) & 0xf];
+   id[4] = vals[(val >> 12) & 0xf];
+   id[5] = vals[(val >>  8) & 0xf];
+   id[6] = vals[(val >>  4) & 0xf];
+   id[7] = vals[(val      ) & 0xf];
+   id[8] = 0;
+   return id;
+}
+
+static Ecore_Evas *
+_ecore_evas_directfb_match(DFBWindowID win)
+{
+   Ecore_Evas *ee;
+   
+   ee = eina_hash_find(ecore_evases_hash, _ecore_evas_directfb_winid_str_get(win));
+   return ee;
+}
+
+static int
+_ecore_evas_directfb_event_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Key_Down *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_key_down(ee->evas, e->name, e->name, e->string,
+                            e->key_compose, e->time, NULL);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Key_Up *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_key_up(ee->evas, e->name, e->name, e->string,
+                          e->key_compose, e->time, NULL);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_motion(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Motion *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_button_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Button_Down *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   // _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   evas_event_feed_mouse_down(ee->evas, e->button, EVAS_BUTTON_NONE, e->time, NULL);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_button_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Button_Up *e;
+   Evas_Button_Flags flags = EVAS_BUTTON_NONE;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   //_ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   evas_event_feed_mouse_up(ee->evas, e->button, flags, e->time, NULL);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_enter(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Enter *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_mouse_in(ee->evas, e->time, NULL);
+   //_ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_leave(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Leave *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_mouse_out(ee->evas, e->time, NULL);
+   //_ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
+   if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_wheel(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Wheel *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_mouse_wheel(ee->evas, e->direction, e->z, e->time, NULL);
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Got_Focus *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   ee->prop.focused = 1;
+   return 1;
+}
+
+static int
+_ecore_evas_directfb_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Event_Lost_Focus *e;
+
+   e = event;
+   ee = _ecore_evas_directfb_match(e->win);
+
+   if (!ee) return 1; /* pass on event */
+   ee->prop.focused = 0;
+   return 1;
+}
+
+int
+_ecore_evas_directfb_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+       int i;
+
+       for (i = 0; i < 8; i++)
+         ecore_event_handler_del(ecore_evas_event_handlers[i]);
+     }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+
+
+
+
+int
+_ecore_evas_directfb_init(void)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+
+   ecore_evas_event_handlers[0]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_KEY_DOWN, _ecore_evas_directfb_event_key_down, NULL);
+   ecore_evas_event_handlers[1]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_KEY_UP, _ecore_evas_directfb_event_key_up, NULL);
+   ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_BUTTON_DOWN, _ecore_evas_directfb_event_button_down, NULL);
+   ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_BUTTON_UP, _ecore_evas_directfb_event_button_up, NULL);
+   ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_MOTION, _ecore_evas_directfb_event_motion, NULL);
+   ecore_evas_event_handlers[5]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_ENTER, _ecore_evas_directfb_event_enter, NULL);
+   ecore_evas_event_handlers[6]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_LEAVE, _ecore_evas_directfb_event_leave, NULL);
+   ecore_evas_event_handlers[7]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_WHEEL, _ecore_evas_directfb_event_wheel, NULL);
+   ecore_evas_event_handlers[8]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_GOT_FOCUS, _ecore_evas_directfb_event_got_focus, NULL);
+   ecore_evas_event_handlers[9]  = ecore_event_handler_add(ECORE_DIRECTFB_EVENT_LOST_FOCUS, _ecore_evas_directfb_event_lost_focus, NULL);
+   ecore_evas_event_handlers[10]  = NULL;
+   ecore_evas_event_handlers[11]  = NULL;
+   ecore_evas_event_handlers[12]  = NULL;
+
+   return _ecore_evas_init_count;
+}
+
+/* engine functions */
+/********************/
+
+static void
+_ecore_evas_directfb_free(Ecore_Evas *ee)
+{
+   eina_hash_del(ecore_evases_hash, _ecore_evas_directfb_winid_str_get(ee->engine.directfb.window->id), ee);
+   ecore_directfb_window_free(ee->engine.directfb.window);
+   _ecore_evas_directfb_shutdown();
+   ecore_directfb_shutdown();
+}
+
+static void
+_ecore_evas_directfb_move(Ecore_Evas *ee, int x, int y)
+{
+   ecore_directfb_window_move(ee->engine.directfb.window, x, y);
+}
+
+static void
+_ecore_evas_directfb_resize(Ecore_Evas *ee, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ecore_directfb_window_resize(ee->engine.directfb.window, w, h);
+   ee->w = w;
+   ee->h = h;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       evas_output_size_set(ee->evas, ee->h, ee->w);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+     }
+   else
+     {
+       evas_output_size_set(ee->evas, ee->w, ee->h);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+     }
+}
+
+static void
+_ecore_evas_directfb_focus_set(Ecore_Evas *ee, int on __UNUSED__)
+{
+   ecore_directfb_window_focus(ee->engine.directfb.window);
+}
+
+static void
+_ecore_evas_directfb_hide(Ecore_Evas *ee)
+{
+   ecore_directfb_window_hide(ee->engine.directfb.window);
+   ee->should_be_visible = 0;
+}
+
+static void
+_ecore_evas_directfb_show(Ecore_Evas *ee)
+{
+   ecore_directfb_window_show(ee->engine.directfb.window);
+   ee->should_be_visible = 1;
+}
+
+static void
+_ecore_evas_directfb_shaped_set(Ecore_Evas *ee, int shaped)
+{
+   if (((ee->shaped) && (shaped)) || ((!ee->shaped) && (!shaped)))
+     return;
+   ee->shaped = shaped;
+   if(ee->shaped)
+     ecore_directfb_window_shaped_set(ee->engine.directfb.window, 1);
+   else
+     ecore_directfb_window_shaped_set(ee->engine.directfb.window, 0);
+
+}
+
+static void
+_ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee)
+     ee->prop.cursor.object = NULL;
+}
+
+static void
+_ecore_evas_directfb_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+       ee->prop.cursor.object = NULL;
+       ee->prop.cursor.layer = 0;
+       ee->prop.cursor.hot.x = 0;
+       ee->prop.cursor.hot.y = 0;
+       ecore_directfb_window_cursor_show(ee->engine.directfb.window, 1);
+       return;
+
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+
+   ecore_directfb_window_cursor_show(ee->engine.directfb.window, 0);
+
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,x - ee->prop.cursor.hot.x,y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+}
+
+static void
+_ecore_evas_directfb_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   Evas_Engine_Info_DirectFB *einfo;
+   int w;
+   int h;
+   int resized = 0;
+
+   if (((ee->prop.fullscreen) && (on)) || ((!ee->prop.fullscreen) && (!on)))
+     return;
+
+   if (on)
+     ecore_directfb_window_fullscreen_set(ee->engine.directfb.window, 1);
+   else
+     ecore_directfb_window_fullscreen_set(ee->engine.directfb.window, 0);
+   /* set the new size of the evas */
+   ecore_directfb_window_size_get(ee->engine.directfb.window, &w, &h);
+   if( (ee->w != w) || (ee->h != h))
+     {
+       resized = 1;
+       ee->w = w;
+       ee->h = h;
+       if ((ee->rotation == 90) || (ee->rotation == 270))
+         {
+            evas_output_size_set(ee->evas, ee->h, ee->w);
+            evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+         }
+       else
+         {
+            evas_output_size_set(ee->evas, ee->w, ee->h);
+            evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+         }
+     }
+   einfo = (Evas_Engine_Info_DirectFB *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       einfo->info.surface = ee->engine.directfb.window->surface;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   ee->prop.fullscreen = on;
+   if (resized)
+     {
+       if(ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+}
+
+static void *
+_ecore_evas_directfb_window_get(const Ecore_Evas *ee)
+{
+   return ee->engine.directfb.window;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+static Ecore_Evas_Engine_Func _ecore_directfb_engine_func =
+{
+   _ecore_evas_directfb_free,  /* free an ecore_evas */
+     NULL,                             /* cb resize */
+     NULL,                             /* cb move */
+     NULL,                             /* cb show */
+     NULL,                             /* cb hide */
+     NULL,                             /* cb delete request */
+     NULL,                             /* cb destroy */
+     NULL,                             /* cb focus in */
+     NULL,                             /* cb focus out */
+     NULL,                              /* cb sticky */
+     NULL,                              /* cb unsticky */
+     NULL,                             /* cb mouse in */
+     NULL,                             /* cb mouse out */
+     NULL,                             /* cb pre render */
+     NULL,                             /* cb post render */
+     _ecore_evas_directfb_move,                /* move */
+     NULL,                              /* managed move */
+     _ecore_evas_directfb_resize,      /* resize */
+     NULL,                             /* move resize */
+     NULL,//_ecore_evas_directfb_rotation_set,/* rotation */
+     _ecore_evas_directfb_shaped_set,   /* shaped */
+     _ecore_evas_directfb_show,                /* show */
+     _ecore_evas_directfb_hide,                /* hide */
+     NULL,                             /* raise */
+     NULL,                             /* lower */
+     NULL,                             /* activate */
+     NULL,                             /* title set */
+     NULL,                             /* name class set */
+     NULL,                             /* size min */
+     NULL,                             /* size max */
+     NULL,                             /* size base */
+     NULL,                             /* size step */
+     _ecore_evas_directfb_object_cursor_set, /* set cursor to an evas object */
+     NULL,                             /* layer set */
+     _ecore_evas_directfb_focus_set,   /* focus */
+     NULL,                             /* iconified */
+     NULL,                             /* borderless */
+     NULL,                             /* override */
+     NULL,                             /* maximized */
+     _ecore_evas_directfb_fullscreen_set,/* fullscreen */
+     NULL,                             /* avoid damage */
+     NULL,                             /* withdrawn */
+     NULL,                             /* sticky */
+     NULL,                              /* ignore events */
+     NULL,                              /* alpha */
+     NULL, //transparent
+     
+     NULL // render
+};
+#endif
+
+/* api */
+/*******/
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+EAPI Ecore_Evas *
+ecore_evas_directfb_new(const char *disp_name, int windowed, int x, int y, int w, int h)
+{
+   Evas_Engine_Info_DirectFB *einfo;
+   Ecore_Evas *ee;
+   Ecore_DirectFB_Window *window;
+   int rmethod;
+
+   rmethod = evas_render_method_lookup("directfb");
+   if (!rmethod) return NULL;
+   if (!ecore_directfb_init(disp_name)) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+   _ecore_evas_directfb_init();
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_directfb_engine_func;
+
+   ee->driver = "directfb";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+
+   ee->rotation = 0;
+   ee->visible = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = w;
+   ee->h = h;
+   ee->prop.layer = 1;
+   ee->prop.fullscreen = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+   einfo = (Evas_Engine_Info_DirectFB *)evas_engine_info_get(ee->evas);
+
+   window = ecore_directfb_window_new(x,y,w,h);
+   ee->engine.directfb.window = window;
+   if (einfo)
+     {
+       einfo->info.dfb = ecore_directfb_interface_get();
+       einfo->info.surface = window->surface;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   
+   ee->engine.func->fn_render = _ecore_evas_directfb_render;
+   _ecore_evas_register(ee);
+   
+   if (!ecore_evases_hash)
+     ecore_evases_hash = eina_hash_string_superfast_new(NULL);
+   eina_hash_add(ecore_evases_hash, _ecore_evas_directfb_winid_str_get(ee->engine.directfb.window->id), ee);
+
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_directfb_new(const char *disp_name __UNUSED__, int windowed __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+EAPI Ecore_DirectFB_Window *
+ecore_evas_directfb_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_DirectFB_Window *) _ecore_evas_directfb_window_get(ee);
+}
+#else
+EAPI Ecore_DirectFB_Window *
+ecore_evas_directfb_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+  return NULL;
+}
+#endif
diff --git a/src/lib/ecore_evas/ecore_evas_fb.c b/src/lib/ecore_evas/ecore_evas_fb.c
new file mode 100644 (file)
index 0000000..3280589
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#ifdef BUILD_ECORE_EVAS_FB
+#include <Ecore_Fb.h>
+#include <ecore_fb_private.h>
+#endif
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_FB
+static int _ecore_evas_init_count = 0;
+
+static char *ecore_evas_default_display = "0";
+static Eina_List *ecore_evas_input_devices = NULL;
+static Ecore_Event_Handler *ecore_evas_event_handlers[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
+
+static void
+_ecore_evas_mouse_move_process_fb(Ecore_Evas *ee, int x, int y, unsigned int timestamp)
+{
+   int fbw, fbh;
+
+   ee->mouse.x = x;
+   ee->mouse.y = y;
+   ecore_fb_size_get(&fbw, &fbh);
+   if (ee->prop.cursor.object)
+     {
+       evas_object_show(ee->prop.cursor.object);
+        if (ee->rotation == 0)
+         evas_object_move(ee->prop.cursor.object,
+                          x - ee->prop.cursor.hot.x,
+                          y - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 90)
+         evas_object_move(ee->prop.cursor.object,
+                          (fbh - ee->h) + ee->h - y - 1 - ee->prop.cursor.hot.x,
+                          x - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 180)
+         evas_object_move(ee->prop.cursor.object,
+                          (fbw - ee->w) + ee->w - x - 1 - ee->prop.cursor.hot.x,
+                          (fbh - ee->h) + ee->h - y - 1 - ee->prop.cursor.hot.y);
+       else if (ee->rotation == 270)
+         evas_object_move(ee->prop.cursor.object,
+                          y - ee->prop.cursor.hot.x,
+                          (fbw - ee->w) + ee->w - x - 1 - ee->prop.cursor.hot.y);
+     }
+   if (ee->rotation == 0)
+     evas_event_feed_mouse_move(ee->evas, x, y, timestamp, NULL);
+   else if (ee->rotation == 90)
+     evas_event_feed_mouse_move(ee->evas, (fbh - ee->h) + ee->h - y - 1, x, timestamp, NULL);
+   else if (ee->rotation == 180)
+     evas_event_feed_mouse_move(ee->evas, (fbw - ee->w) + ee->w - x - 1, (fbh - ee->h) + ee->h - y - 1, timestamp, NULL);
+   else if (ee->rotation == 270)
+     evas_event_feed_mouse_move(ee->evas, y, (fbw - ee->w) + ee->w - x - 1, timestamp, NULL);
+}
+
+static Ecore_Evas *fb_ee = NULL;
+
+static Ecore_Evas *
+_ecore_evas_fb_match(void)
+{
+   return fb_ee;
+}
+
+static void
+_ecore_evas_fb_lose(void *data __UNUSED__)
+{
+   Ecore_Evas *ee;
+   Eina_List *ll;
+   Ecore_Fb_Input_Device *dev;
+
+   if (fb_ee) fb_ee->visible = 0;
+
+   EINA_LIST_FOREACH(ecore_evas_input_devices, ll, dev)
+     ecore_fb_input_device_listen(dev, 0);
+}
+
+static void
+_ecore_evas_fb_gain(void *data __UNUSED__)
+{
+   Ecore_Evas *ee;
+   Eina_List *ll;
+   Ecore_Fb_Input_Device *dev;
+
+   if (fb_ee) 
+     {
+        ee = fb_ee;
+        
+       ee->visible = 1;
+       if ((ee->rotation == 90) || (ee->rotation == 270))
+         evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+       else
+         evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+
+   EINA_LIST_FOREACH(ecore_evas_input_devices, ll, dev)
+     ecore_fb_input_device_listen(dev, 1);
+}
+
+static int
+_ecore_evas_event_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Key_Down *e;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_key_down(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_event_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Key_Up *e;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   evas_event_feed_key_up(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_event_mouse_button_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Mouse_Button_Down *e;
+   Evas_Button_Flags flags = EVAS_BUTTON_NONE;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   _ecore_evas_mouse_move_process_fb(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff));
+   if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
+   if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
+   evas_event_feed_mouse_down(ee->evas, e->button, flags, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_event_mouse_button_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Mouse_Button_Up *e;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   _ecore_evas_mouse_move_process_fb(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff));
+   evas_event_feed_mouse_up(ee->evas, e->button, EVAS_BUTTON_NONE, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Mouse_Move *e;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   _ecore_evas_mouse_move_process_fb(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff));
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_event_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Fb_Event_Mouse_Wheel *e;
+
+   e = event;
+   ee = _ecore_evas_fb_match();
+   if (!ee) return 1; /* pass on event */
+   _ecore_evas_mouse_move_process_fb(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff));
+   return 0; /* dont pass it on */
+}
+
+static int
+_ecore_evas_fb_render(Ecore_Evas *ee)
+{
+   int rend = 0;
+
+   if (ee->visible)
+     {
+        Eina_List *updates;
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+        Eina_List *ll;
+        Ecore_Evas *ee2;
+#endif
+        if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+        EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+          {
+             if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+             rend |= _ecore_evas_buffer_render(ee2);
+             if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+          }
+#endif
+        updates = evas_render_updates(ee->evas);
+        if (updates)
+          {
+             evas_render_updates_free(updates);
+             _ecore_evas_idle_timeout_update(ee);
+             rend = 1;
+          }
+        if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+     }
+   else
+     evas_norender(ee->evas);
+   return rend;
+}
+
+static int
+_ecore_evas_fb_init(int w, int h)
+{
+   Ecore_Fb_Input_Device *device;
+   Ecore_Fb_Input_Device_Cap caps;
+   int mouse_handled = 0;
+   int keyboard_handled = 0;
+
+   DIR *input_dir;
+   struct dirent *input_entry;
+
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+
+   /* register all input devices */
+   input_dir = opendir("/dev/input/");
+   if (!input_dir) return _ecore_evas_init_count;
+
+   while ((input_entry = readdir(input_dir)))
+     {
+       char device_path[256];
+
+       if (strncmp(input_entry->d_name, "event", 5) != 0)
+         continue;
+
+       snprintf(device_path, 256, "/dev/input/%s", input_entry->d_name);
+       if (!(device = ecore_fb_input_device_open(device_path)))
+         continue;
+
+       caps = ecore_fb_input_device_cap_get(device);
+
+       /* Mouse */
+#ifdef HAVE_TSLIB
+       if (caps & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE)
+#else
+       if ((caps & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE) || (caps & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE))
+#endif
+         {
+            ecore_fb_input_device_axis_size_set(device, w, h);
+            ecore_fb_input_device_listen(device,1);
+            ecore_evas_input_devices = eina_list_append(ecore_evas_input_devices, device);
+            if (!mouse_handled)
+              {
+                 ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, _ecore_evas_event_mouse_button_down, NULL);
+                 ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, _ecore_evas_event_mouse_button_up, NULL);
+                 ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_MOVE, _ecore_evas_event_mouse_move, NULL);
+                 ecore_evas_event_handlers[5]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_WHEEL, _ecore_evas_event_mouse_wheel, NULL);
+                 mouse_handled = 1;
+              }
+         }
+       /* Keyboard */
+       else if ((caps & ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS) && !(caps & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE))
+         {
+            ecore_fb_input_device_listen(device,1);
+            ecore_evas_input_devices = eina_list_append(ecore_evas_input_devices, device);
+            if (!keyboard_handled)
+              {
+                 ecore_evas_event_handlers[0]  = ecore_event_handler_add(ECORE_FB_EVENT_KEY_DOWN, _ecore_evas_event_key_down, NULL);
+                 ecore_evas_event_handlers[1]  = ecore_event_handler_add(ECORE_FB_EVENT_KEY_UP, _ecore_evas_event_key_up, NULL);
+                 keyboard_handled = 1;
+              }
+         }
+     }
+   if (!mouse_handled)
+     {
+       if (ecore_fb_ts_init())
+         {
+            ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, _ecore_evas_event_mouse_button_down, NULL);
+            ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, _ecore_evas_event_mouse_button_up, NULL);
+            ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_MOVE, _ecore_evas_event_mouse_move, NULL);
+            mouse_handled = 1;
+         }
+     }
+   return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_fb_free(Ecore_Evas *ee)
+{
+   if (fb_ee == ee) fb_ee = NULL;
+   _ecore_evas_fb_shutdown();
+   ecore_fb_shutdown();
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       evas_output_size_set(ee->evas, ee->h, ee->w);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+     }
+   else
+     {
+       evas_output_size_set(ee->evas, ee->w, ee->h);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     {
+       evas_output_size_set(ee->evas, ee->h, ee->w);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+     }
+   else
+     {
+       evas_output_size_set(ee->evas, ee->w, ee->h);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_rotation_set(Ecore_Evas *ee, int rotation, int resize)
+{
+   Evas_Engine_Info_FB *einfo;
+   int rot_dif;
+
+   if (ee->rotation == rotation) return;
+   einfo = (Evas_Engine_Info_FB *)evas_engine_info_get(ee->evas);
+   if (!einfo) return;
+   rot_dif = ee->rotation - rotation;
+   if (rot_dif < 0) rot_dif = -rot_dif;
+   if (rot_dif != 180)
+     {
+
+       einfo->info.rotation = rotation;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+       if (!ee->prop.fullscreen)
+         {
+            int tmp;
+
+            tmp = ee->w;
+            ee->w = ee->h;
+            ee->h = tmp;
+         }
+       else
+         {
+            if ((rotation == 0) || (rotation == 180))
+              {
+                 evas_output_size_set(ee->evas, ee->w, ee->h);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+              }
+            else
+              {
+                 evas_output_size_set(ee->evas, ee->h, ee->w);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+              }
+         }
+       ee->rotation = rotation;
+     }
+   else
+     {
+       einfo->info.rotation = rotation;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+       ee->rotation = rotation;
+     }
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+   else
+     evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+   _ecore_evas_mouse_move_process_fb(ee, ee->mouse.x, ee->mouse.y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff));
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee)
+     ee->prop.cursor.object = NULL;
+}
+
+static void
+_ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+       ee->prop.cursor.object = NULL;
+       ee->prop.cursor.layer = 0;
+       ee->prop.cursor.hot.x = 0;
+       ee->prop.cursor.hot.y = 0;
+       return;
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                   x - ee->prop.cursor.hot.x,
+                   y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+}
+
+static void
+_ecore_evas_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   Eina_List *l;
+   Ecore_Fb_Input_Device *dev;
+   int resized = 0;
+
+   if (((ee->prop.fullscreen) && (on)) ||
+       ((!ee->prop.fullscreen) && (!on))) return;
+   if (on)
+     {
+       int w, h;
+
+       ee->engine.fb.real_w = ee->w;
+       ee->engine.fb.real_h = ee->h;
+       w = ee->w;
+       h = ee->h;
+       ecore_fb_size_get(&w, &h);
+       if ((w == 0) && (h == 0))
+         {
+            w = ee->w;
+            h = ee->h;
+         }
+       if ((w != ee->w) || (h != ee->h)) resized = 1;
+       ee->w = w;
+       ee->h = h;
+       evas_output_size_set(ee->evas, ee->w, ee->h);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+   else
+     {
+       if ((ee->engine.fb.real_w != ee->w) || (ee->engine.fb.real_h != ee->h)) resized = 1;
+       ee->w = ee->engine.fb.real_w;
+       ee->h = ee->engine.fb.real_h;
+       evas_output_size_set(ee->evas, ee->w, ee->h);
+       evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+   ee->prop.fullscreen = on;
+   EINA_LIST_FOREACH(ecore_evas_input_devices, l, dev)
+     ecore_fb_input_device_axis_size_set(dev, ee->w, ee->h);
+   /* rescale the input device area */
+   if (resized)
+     {
+       if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+}
+
+int
+_ecore_evas_fb_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+       int i;
+
+       for (i = 0; i < 6; i++)
+          {
+             if (ecore_evas_event_handlers[i])
+               ecore_event_handler_del(ecore_evas_event_handlers[i]);
+          }
+       ecore_fb_ts_shutdown();
+     }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+static Ecore_Evas_Engine_Func _ecore_fb_engine_func =
+{
+   _ecore_evas_fb_free,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_resize,
+     _ecore_evas_move_resize,
+     _ecore_evas_rotation_set,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_object_cursor_set,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_fullscreen_set,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL, //transparent
+     
+     NULL // render
+};
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_FB
+EAPI Ecore_Evas *
+ecore_evas_fb_new(const char *disp_name, int rotation, int w, int h)
+{
+   Evas_Engine_Info_FB *einfo;
+   Ecore_Evas *ee;
+
+   int rmethod;
+
+   if (!disp_name)
+   disp_name = ecore_evas_default_display;
+
+   rmethod = evas_render_method_lookup("fb");
+   if (!rmethod) return NULL;
+
+   if (!ecore_fb_init(disp_name)) return NULL;
+   ecore_fb_callback_gain_set(_ecore_evas_fb_gain, NULL);
+   ecore_fb_callback_lose_set(_ecore_evas_fb_lose, NULL);
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_fb_init(w, h);
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_fb_engine_func;
+
+   ee->driver = "fb";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->rotation = rotation;
+   ee->visible = 1;
+   ee->w = w;
+   ee->h = h;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = 1;
+   ee->prop.borderless = 1;
+   ee->prop.override = 1;
+   ee->prop.maximized = 1;
+   ee->prop.fullscreen = 0;
+   ee->prop.withdrawn = 0;
+   ee->prop.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+
+   if ((rotation == 90) || (rotation == 270))
+     {
+       evas_output_size_set(ee->evas, h, w);
+       evas_output_viewport_set(ee->evas, 0, 0, h, w);
+     }
+   else
+     {
+       evas_output_size_set(ee->evas, w, h);
+       evas_output_viewport_set(ee->evas, 0, 0, w, h);
+     }
+
+   einfo = (Evas_Engine_Info_FB *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       einfo->info.virtual_terminal = 0;
+       einfo->info.device_number = strtol(disp_name, NULL, 10);
+       einfo->info.refresh = 0;
+       einfo->info.rotation = ee->rotation;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+   evas_key_modifier_add(ee->evas, "Shift");
+   evas_key_modifier_add(ee->evas, "Control");
+   evas_key_modifier_add(ee->evas, "Alt");
+   evas_key_modifier_add(ee->evas, "Meta");
+   evas_key_modifier_add(ee->evas, "Hyper");
+   evas_key_modifier_add(ee->evas, "Super");
+   evas_key_lock_add(ee->evas, "Caps_Lock");
+   evas_key_lock_add(ee->evas, "Num_Lock");
+   evas_key_lock_add(ee->evas, "Scroll_Lock");
+
+   ee->engine.func->fn_render = _ecore_evas_buffer_render;
+   _ecore_evas_register(ee);
+   fb_ee = ee;
+   
+   evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   evas_focus_in(ee->evas);
+
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_fb_new(const char *disp_name __UNUSED__, int rotation __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+#endif
diff --git a/src/lib/ecore_evas/ecore_evas_private.h b/src/lib/ecore_evas/ecore_evas_private.h
new file mode 100644 (file)
index 0000000..24b027d
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#ifndef _ECORE_EVAS_PRIVATE_H
+#define _ECORE_EVAS_PRIVATE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include <Evas.h>
+#include <ecore_private.h>
+#include <Ecore_Input.h>
+#include <Ecore_Input_Evas.h>
+
+#define ECORE_MAGIC_EVAS 0x76543211
+
+#ifndef BUILD_ECORE_DIRECTFB
+# undef BUILD_ECORE_EVAS_DIRECTFB
+#endif
+
+#ifdef BUILD_ECORE_EVAS_X11
+# include "Ecore_X.h"
+# ifdef HAVE_ECORE_X_XCB
+#  include <xcb/xcb.h>
+#  ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+#   include <Evas_Engine_Software_X11.h>
+#  endif
+#  ifdef BUILD_ECORE_EVAS_XRENDER_XCB
+#   include <xcb/render.h>
+#   include <Evas_Engine_XRender_X11.h>
+#  endif
+# endif
+# ifdef HAVE_ECORE_X_XLIB
+#  include <X11/Xlib.h>
+#  include <X11/Xutil.h>
+#  ifdef BUILD_ECORE_EVAS_SOFTWARE_XLIB
+#   include <Evas_Engine_Software_X11.h>
+#  endif
+#  ifdef BUILD_ECORE_EVAS_XRENDER_X11
+#   include <X11/extensions/Xrender.h>
+#   include <Evas_Engine_XRender_X11.h>
+#  endif
+#  ifdef BUILD_ECORE_EVAS_OPENGL_X11
+#    include <Evas_Engine_GL_X11.h>
+#  endif
+#  ifdef BUILD_ECORE_EVAS_SOFTWARE_16_X11
+#   include <Evas_Engine_Software_16_X11.h>
+#  endif
+# endif
+#endif
+
+#ifdef BUILD_ECORE_EVAS_FB
+# include <Evas_Engine_FB.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+# include <Evas_Engine_DirectFB.h>
+# include "Ecore_DirectFB.h"
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+# include <Evas_Engine_Buffer.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WIN32
+# include "Ecore_Win32.h"
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+#  include <Evas_Engine_Software_Gdi.h>
+# endif
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+#  include <Evas_Engine_Software_DDraw.h>
+# endif
+# ifdef BUILD_ECORE_EVAS_DIRECT3D
+#  include <Evas_Engine_Direct3D.h>
+# endif
+# ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+#  include <Evas_Engine_GL_Glew.h>
+# endif
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+#  include <Evas_Engine_Software_16_DDraw.h>
+# endif
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+# include "Ecore_WinCE.h"
+# include <Evas_Engine_Software_16_WinCE.h>
+#endif
+
+/**
+   Log domain macros and variable
+ **/
+
+extern int _ecore_evas_log_dom;
+
+#ifdef ECORE_EVAS_DEFAULT_LOG_COLOR
+# undef ECORE_EVAS_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_EVAS_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_evas_log_dom, __VA_ARGS__)
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_evas_log_dom, __VA_ARGS__)
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_evas_log_dom, __VA_ARGS__)
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_evas_log_dom, __VA_ARGS__)
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_evas_log_dom, __VA_ARGS__)
+
+
+#define IDLE_FLUSH_TIME 0.5
+#ifndef _ECORE_EVAS_H
+typedef struct _Ecore_Evas Ecore_Evas;
+#endif
+
+typedef struct _Ecore_Evas_Engine      Ecore_Evas_Engine;
+typedef struct _Ecore_Evas_Engine_Func Ecore_Evas_Engine_Func;
+
+struct _Ecore_Evas_Engine_Func
+{
+   void        (*fn_free) (Ecore_Evas *ee);
+   void        (*fn_callback_resize_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_move_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_show_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_hide_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_delete_request_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_destroy_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_focus_in_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_focus_out_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_mouse_in_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_mouse_out_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_sticky_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_unsticky_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_pre_render_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_callback_post_render_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee));
+   void        (*fn_move) (Ecore_Evas *ee, int x, int y);
+   void        (*fn_managed_move) (Ecore_Evas *ee, int x, int y);
+   void        (*fn_resize) (Ecore_Evas *ee, int w, int h);
+   void        (*fn_move_resize) (Ecore_Evas *ee, int x, int y, int w, int h);
+   void        (*fn_rotation_set) (Ecore_Evas *ee, int rot, int resize);
+   void        (*fn_shaped_set) (Ecore_Evas *ee, int shaped);
+   void        (*fn_show) (Ecore_Evas *ee);
+   void        (*fn_hide) (Ecore_Evas *ee);
+   void        (*fn_raise) (Ecore_Evas *ee);
+   void        (*fn_lower) (Ecore_Evas *ee);
+   void        (*fn_activate) (Ecore_Evas *ee);
+   void        (*fn_title_set) (Ecore_Evas *ee, const char *t);
+   void        (*fn_name_class_set) (Ecore_Evas *ee, const char *n, const char *c);
+   void        (*fn_size_min_set) (Ecore_Evas *ee, int w, int h);
+   void        (*fn_size_max_set) (Ecore_Evas *ee, int w, int h);
+   void        (*fn_size_base_set) (Ecore_Evas *ee, int w, int h);
+   void        (*fn_size_step_set) (Ecore_Evas *ee, int w, int h);
+   void        (*fn_object_cursor_set) (Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y);
+   void        (*fn_layer_set) (Ecore_Evas *ee, int layer);
+   void        (*fn_focus_set) (Ecore_Evas *ee, int on);
+   void        (*fn_iconified_set) (Ecore_Evas *ee, int on);
+   void        (*fn_borderless_set) (Ecore_Evas *ee, int on);
+   void        (*fn_override_set) (Ecore_Evas *ee, int on);
+   void        (*fn_maximized_set) (Ecore_Evas *ee, int on);
+   void        (*fn_fullscreen_set) (Ecore_Evas *ee, int on);
+   void        (*fn_avoid_damage_set) (Ecore_Evas *ee, int on);
+   void        (*fn_withdrawn_set) (Ecore_Evas *ee, int withdrawn);
+   void        (*fn_sticky_set) (Ecore_Evas *ee, int sticky);
+   void        (*fn_ignore_events_set) (Ecore_Evas *ee, int ignore);
+   void        (*fn_alpha_set) (Ecore_Evas *ee, int alpha);
+   void        (*fn_transparent_set) (Ecore_Evas *ee, int transparent);
+
+   int         (*fn_render) (Ecore_Evas *ee);
+};
+
+struct _Ecore_Evas_Engine
+{
+   Ecore_Evas_Engine_Func *func;
+
+#ifdef BUILD_ECORE_EVAS_X11
+   struct {
+      Ecore_X_Window win_root;
+      Eina_List     *win_extra;
+      Ecore_X_Pixmap pmap;
+      Ecore_X_Pixmap mask;
+      Ecore_X_GC     gc;
+      Ecore_X_XRegion *damages;
+      Ecore_X_Sync_Counter sync_counter;
+      int            sync_val; // bigger! this will screw up at 2 billion frames (414 days of continual rendering @ 60fps)
+      int            screen_num;
+      int            px, py, pw, ph;
+      unsigned char  direct_resize : 1;
+      unsigned char  using_bg_pixmap : 1;
+      unsigned char  managed : 1;
+      unsigned char  sync_began : 1;
+      unsigned char  sync_cancel : 1;
+      struct {
+          unsigned char modal : 1;
+          unsigned char sticky : 1;
+          unsigned char maximized_v : 1;
+          unsigned char maximized_h : 1;
+          unsigned char shaded : 1;
+          unsigned char skip_taskbar : 1;
+          unsigned char skip_pager : 1;
+          unsigned char fullscreen : 1;
+          unsigned char above : 1;
+          unsigned char below : 1;
+      } state;
+   } x;
+#endif
+#ifdef BUILD_ECORE_EVAS_FB
+   struct {
+      int real_w;
+      int real_h;
+   } fb;
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   struct {
+      void *pixels;
+      Evas_Object *image;
+   } buffer;
+#endif
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+   struct {
+      Ecore_DirectFB_Window *window;
+   } directfb;
+#endif
+#ifdef BUILD_ECORE_EVAS_WIN32
+   struct {
+      Ecore_Win32_Window *parent;
+     struct {
+       unsigned char fullscreen : 1;
+     } state;
+   } win32;
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+   struct {
+      Ecore_WinCE_Window *window;
+     struct {
+       unsigned char fullscreen : 1;
+     } state;
+   } wince;
+#endif
+
+   Ecore_Timer *idle_flush_timer;
+};
+
+struct _Ecore_Evas
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+   Evas       *evas;
+   const char *driver;
+   char       *name;
+   int         x, y, w, h;
+   short       rotation;
+   Eina_Bool   shaped  : 1;
+   Eina_Bool   visible : 1;
+   Eina_Bool   draw_ok : 1;
+   Eina_Bool   should_be_visible : 1;
+   Eina_Bool   alpha  : 1;
+   Eina_Bool   transparent  : 1;
+
+   Eina_Hash  *data;
+
+   struct {
+      int      x, y, w, h;
+   } req;
+   
+   struct {
+      int      x, y;
+   } mouse;
+
+   struct {
+      int      w, h;
+   } expecting_resize;
+
+   struct {
+      char           *title;
+      char           *name;
+      char           *clas;
+      struct {
+        int          w, h;
+      } min,
+       max,
+       base,
+       step;
+      struct {
+        Evas_Object *object;
+        int          layer;
+        struct {
+           int       x, y;
+        } hot;
+      } cursor;
+      int             layer;
+      Ecore_Window    window;
+      unsigned char   avoid_damage;
+      char            focused      : 1;
+      char            iconified    : 1;
+      char            borderless   : 1;
+      char            override     : 1;
+      char            maximized    : 1;
+      char            fullscreen   : 1;
+      char            withdrawn    : 1;
+      char            sticky       : 1;
+      char            request_pos  : 1;
+   } prop;
+
+   struct {
+      void          (*fn_resize) (Ecore_Evas *ee);
+      void          (*fn_move) (Ecore_Evas *ee);
+      void          (*fn_show) (Ecore_Evas *ee);
+      void          (*fn_hide) (Ecore_Evas *ee);
+      void          (*fn_delete_request) (Ecore_Evas *ee);
+      void          (*fn_destroy) (Ecore_Evas *ee);
+      void          (*fn_focus_in) (Ecore_Evas *ee);
+      void          (*fn_focus_out) (Ecore_Evas *ee);
+      void          (*fn_sticky) (Ecore_Evas *ee);
+      void          (*fn_unsticky) (Ecore_Evas *ee);
+      void          (*fn_mouse_in) (Ecore_Evas *ee);
+      void          (*fn_mouse_out) (Ecore_Evas *ee);
+      void          (*fn_pre_render) (Ecore_Evas *ee);
+      void          (*fn_post_render) (Ecore_Evas *ee);
+      void          (*fn_pre_free) (Ecore_Evas *ee);
+   } func;
+
+   Ecore_Evas_Engine engine;
+   Eina_List *sub_ecore_evas;
+
+   unsigned char ignore_events : 1;
+   unsigned char manual_render : 1;
+   unsigned char registered : 1;
+   unsigned char no_comp_sync  : 1;
+};
+
+#ifdef BUILD_ECORE_EVAS_X11
+int _ecore_evas_x_shutdown(void);
+#endif
+#ifdef BUILD_ECORE_EVAS_FB
+int _ecore_evas_fb_shutdown(void);
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+int _ecore_evas_buffer_shutdown(void);
+int _ecore_evas_buffer_render(Ecore_Evas *ee);
+#endif
+#ifdef BUILD_ECORE_EVAS_DIRECTFB
+int _ecore_evas_directfb_shutdown(void);
+#endif
+#ifdef BUILD_ECORE_EVAS_WIN32
+int _ecore_evas_win32_shutdown(void);
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+int _ecore_evas_wince_shutdown(void);
+#endif
+
+void _ecore_evas_fps_debug_init(void);
+void _ecore_evas_fps_debug_shutdown(void);
+void _ecore_evas_fps_debug_rendertime_add(double t);
+void _ecore_evas_register(Ecore_Evas *ee);
+void _ecore_evas_free(Ecore_Evas *ee);
+void _ecore_evas_idle_timeout_update(Ecore_Evas *ee);
+void _ecore_evas_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int timestamp);
+
+extern int _ecore_evas_app_comp_sync;
+
+#endif
diff --git a/src/lib/ecore_evas/ecore_evas_sdl.c b/src/lib/ecore_evas/ecore_evas_sdl.c
new file mode 100644 (file)
index 0000000..153c87e
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Input.h>
+#include <Ecore_Input_Evas.h>
+#if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
+# include <Ecore_Sdl.h>
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+#  include <Evas_Engine_SDL.h>
+# endif
+# ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+#  include <Evas_Engine_GL_SDL.h>
+# endif
+#endif
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+// fixme: 1 sdl window only at a time? seems wrong
+
+#if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
+
+/* static char *ecore_evas_default_display = "0"; */
+/* static Ecore_List *ecore_evas_input_devices = NULL; */
+
+static int                      _ecore_evas_init_count = 0;
+
+static Ecore_Evas               *sdl_ee = NULL;
+static Ecore_Event_Handler      *ecore_evas_event_handlers[4] = {
+   NULL, NULL, NULL, NULL
+};
+
+static const char               *ecore_evas_sdl_default = "EFL SDL";
+static int                      _ecore_evas_fps_debug = 0;
+static Ecore_Poller             *ecore_evas_event;
+static Ecore_Evas              *ecore_evases = NULL;
+
+static Ecore_Evas *
+_ecore_evas_sdl_match(void)
+{
+   return sdl_ee;
+}
+
+static int
+_ecore_evas_sdl_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+   Ecore_Evas                   *ee;
+
+   ee = _ecore_evas_sdl_match();
+
+   if (!ee) return 1;
+   /* pass on event */
+   ee->prop.focused = 1;
+
+   return 0;
+}
+
+static int
+_ecore_evas_sdl_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+   Ecore_Evas                   *ee;
+
+   ee = _ecore_evas_sdl_match();
+
+   if (!ee) return 1;
+   /* pass on event */
+   ee->prop.focused = 0;
+
+   return 0;
+}
+
+static int
+_ecore_evas_sdl_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Sdl_Event_Video_Resize *e;
+   Ecore_Evas                   *ee;
+
+   e = event;
+   ee = _ecore_evas_sdl_match();
+
+   if (!ee) return 1; /* pass on event */
+   evas_output_size_set(ee->evas, e->w, e->h);
+
+   return 0;
+}
+
+static int
+_ecore_evas_sdl_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
+{
+   Ecore_Evas                   *ee;
+   int                          w;
+   int                          h;
+
+   ee = _ecore_evas_sdl_match();
+
+   if (!ee) return 1;
+   evas_output_size_get(ee->evas, &w, &h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
+
+   return 0;
+}
+
+static int
+_ecore_evas_render(Ecore_Evas *ee)
+{
+   Eina_List *updates;
+
+   updates = evas_render_updates(ee->evas);
+   if (updates)
+     {
+       evas_render_updates_free(updates);
+       _ecore_evas_idle_timeout_update(ee);
+     }
+   return updates ? 1 : 0;
+}
+
+static int
+_ecore_evas_sdl_render(Ecore_Evas *ee)
+{
+   int rend = 0;
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Eina_List *ll;
+   Ecore_Evas *ee2;
+
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+        if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+        rend |= _ecore_evas_buffer_render(ee2);
+        if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+#endif
+
+   if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+
+   if (ee->prop.avoid_damage) rend = _ecore_evas_render(ee);
+   else if ((ee->visible) ||
+            ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
+            ((ee->should_be_visible) && (ee->prop.override)))
+     rend |= _ecore_evas_render(ee);
+   else
+     evas_norender(ee->evas);
+
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+   return rend;
+}
+
+static int
+_ecore_evas_sdl_event(void *data __UNUSED__)
+{
+   ecore_sdl_feed_events();
+   return 1;
+}
+
+static int
+_ecore_evas_sdl_init(int w __UNUSED__, int h __UNUSED__)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+
+#ifndef _WIN32
+   if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1;
+#endif /* _WIN32 */
+   // this is pretty bad: poller? and set poll time? pol time is meant to be 
+   // adjustable for things like polling battery state, or amoutn of spare
+   // memory etc.
+   // 
+   ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, _ecore_evas_sdl_event, NULL);
+   ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
+#ifndef _WIN32
+   if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init();
+#endif /* _WIN32 */
+
+   ecore_event_evas_init();
+
+   ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_SDL_EVENT_GOT_FOCUS, _ecore_evas_sdl_event_got_focus, NULL);
+   ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_SDL_EVENT_LOST_FOCUS, _ecore_evas_sdl_event_lost_focus, NULL);
+   ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_SDL_EVENT_RESIZE, _ecore_evas_sdl_event_video_resize, NULL);
+   ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_SDL_EVENT_EXPOSE, _ecore_evas_sdl_event_video_expose, NULL);
+
+   return _ecore_evas_init_count;
+}
+
+static int
+_ecore_evas_sdl_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+       int i;
+
+        for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
+         ecore_event_handler_del(ecore_evas_event_handlers[i]);
+       ecore_event_evas_shutdown();
+        ecore_poller_del(ecore_evas_event);
+        ecore_evas_event = NULL;
+#ifndef _WIN32
+       if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown();
+#endif /* _WIN32 */
+     }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_sdl_free(Ecore_Evas *ee)
+{
+   if (sdl_ee == ee) sdl_ee = NULL;
+   
+   ecore_event_window_unregister(0);
+   _ecore_evas_sdl_shutdown();
+   ecore_sdl_shutdown();
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
+{
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee)
+     ee->prop.cursor.object = NULL;
+}
+
+static void
+_ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+       ee->prop.cursor.object = NULL;
+       ee->prop.cursor.layer = 0;
+       ee->prop.cursor.hot.x = 0;
+       ee->prop.cursor.hot.y = 0;
+       return;
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                   x - ee->prop.cursor.hot.x,
+                   y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+}
+
+static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
+{
+   _ecore_evas_sdl_free,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_resize,
+   _ecore_evas_move_resize,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_object_cursor_set,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL, //transparent
+     
+     NULL // render
+};
+
+static Ecore_Evas*
+_ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
+{
+   void                 *einfo;
+   Ecore_Evas           *ee;
+
+   if (!name)
+     name = ecore_evas_sdl_default;
+
+   if (ecore_evases) return NULL;
+
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_sdl_engine_func;
+
+   ee->driver = "sdl";
+   if (name) ee->name = strdup(name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->visible = 1;
+   ee->w = w;
+   ee->h = h;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = 1;
+   ee->prop.borderless = 1;
+   ee->prop.override = 1;
+   ee->prop.maximized = 1;
+   ee->prop.fullscreen = fullscreen;
+   ee->prop.withdrawn = 0;
+   ee->prop.sticky = 0;
+   ee->prop.window = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   if (rmethod == evas_render_method_lookup("software_sdl"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+       einfo = evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            ((Evas_Engine_Info_SDL *)einfo)->info.rotation = 0;
+            ((Evas_Engine_Info_SDL *)einfo)->info.fullscreen = fullscreen;
+            ((Evas_Engine_Info_SDL *)einfo)->info.hwsurface = hwsurface;
+            ((Evas_Engine_Info_SDL *)einfo)->info.noframe = noframe;
+            ((Evas_Engine_Info_SDL *)einfo)->info.alpha = alpha;
+            evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+         }
+#endif
+     }
+   else if (rmethod == evas_render_method_lookup("gl_sdl"))
+     {
+#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+       einfo = evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            ((Evas_Engine_Info_GL_SDL *)einfo)->flags.fullscreen = fullscreen;
+            ((Evas_Engine_Info_GL_SDL *)einfo)->flags.noframe = noframe;
+            evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+         }
+#endif
+     }
+
+   if (!ecore_sdl_init(name))
+     {
+       evas_free(ee->evas);
+       if (ee->name) free(ee->name);
+       free(ee);
+       return NULL;
+     }
+
+   _ecore_evas_sdl_init(w, h);
+
+   ecore_event_window_register(0, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+
+   SDL_ShowCursor(SDL_DISABLE);
+
+   ee->engine.func->fn_render = _ecore_evas_sdl_render;
+   _ecore_evas_register(ee);
+   
+   sdl_ee = ee;
+   
+   evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+   evas_focus_in(ee->evas);
+
+   return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+EAPI Ecore_Evas*
+ecore_evas_sdl_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
+{
+   Ecore_Evas          *ee;
+   int                  rmethod;
+
+   rmethod = evas_render_method_lookup("software_sdl");
+   if (!rmethod) return NULL;
+
+   ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
+   ee->driver = "sdl";
+   return ee;
+}
+#else
+EAPI Ecore_Evas*
+ecore_evas_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
+{
+   ERR("OUTCH !");
+   return NULL;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
+EAPI Ecore_Evas*
+ecore_evas_sdl16_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
+{
+   Ecore_Evas          *ee;
+   int                  rmethod;
+
+   rmethod = evas_render_method_lookup("software_16_sdl");
+   if (!rmethod) return NULL;
+
+   ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
+   ee->driver = "software_16_sdl";
+   return ee;
+}
+#else
+EAPI Ecore_Evas*
+ecore_evas_sdl16_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
+{
+   ERR("OUTCH !");
+   return NULL;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
+EAPI Ecore_Evas*
+ecore_evas_gl_sdl_new(const char* name, int w, int h, int fullscreen, int noframe)
+{
+   Ecore_Evas          *ee;
+   int                  rmethod;
+
+   rmethod = evas_render_method_lookup("gl_sdl");
+   if (!rmethod) return NULL;
+
+   ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, 0, noframe, 0);
+   ee->driver = "gl_sdl";
+   return ee;
+}
+#else
+EAPI Ecore_Evas*
+ecore_evas_gl_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int noframe __UNUSED__)
+{
+   ERR("OUTCH !");
+   return NULL;
+}
+#endif
+
diff --git a/src/lib/ecore_evas/ecore_evas_util.c b/src/lib/ecore_evas/ecore_evas_util.c
new file mode 100644 (file)
index 0000000..3caa6a4
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <Ecore.h>
+#include "ecore_private.h"
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+static const char ASSOCIATE_KEY[] = "__Ecore_Evas_Associate";
+
+static void _ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags);
+static void _ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj);
+
+
+static Evas_Object *
+_ecore_evas_associate_get(const Ecore_Evas *ee)
+{
+   return ecore_evas_data_get(ee, ASSOCIATE_KEY);
+}
+
+static void
+_ecore_evas_associate_set(Ecore_Evas *ee, Evas_Object *obj)
+{
+   ecore_evas_data_set(ee, ASSOCIATE_KEY, obj);
+}
+
+static void
+_ecore_evas_associate_del(Ecore_Evas *ee)
+{
+   ecore_evas_data_set(ee, ASSOCIATE_KEY, NULL);
+}
+
+static Ecore_Evas *
+_evas_object_associate_get(const Evas_Object *obj)
+{
+   return evas_object_data_get(obj, ASSOCIATE_KEY);
+}
+
+static void
+_evas_object_associate_set(Evas_Object *obj, Ecore_Evas *ee)
+{
+   evas_object_data_set(obj, ASSOCIATE_KEY, ee);
+}
+
+static void
+_evas_object_associate_del(Evas_Object *obj)
+{
+   evas_object_data_del(obj, ASSOCIATE_KEY);
+}
+
+/** Associated Events: ******************************************************/
+
+/* Interceptors Callbacks */
+
+static void
+_ecore_evas_obj_intercept_move(void *data, Evas_Object *obj __UNUSED__, Evas_Coord x, Evas_Coord y)
+{
+   Ecore_Evas *ee = data;
+   // FIXME: account for frame
+   ecore_evas_move(ee, x, y);
+}
+
+static void
+_ecore_evas_obj_intercept_raise(void *data, Evas_Object *obj __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_raise(ee);
+}
+
+static void
+_ecore_evas_obj_intercept_lower(void *data, Evas_Object *obj __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_lower(ee);
+}
+
+static void
+_ecore_evas_obj_intercept_stack_above(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *above __UNUSED__)
+{
+   INF("TODO: %s", __FUNCTION__);
+}
+
+static void
+_ecore_evas_obj_intercept_stack_below(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *below __UNUSED__)
+{
+   INF("TODO: %s", __FUNCTION__);
+}
+
+static void
+_ecore_evas_obj_intercept_layer_set(void *data, Evas_Object *obj __UNUSED__, int l)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_layer_set(ee, l);
+}
+
+/* Event Callbacks */
+
+static void
+_ecore_evas_obj_callback_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_show(ee);
+}
+
+static void
+_ecore_evas_obj_callback_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   ecore_evas_hide(ee);
+}
+
+static void
+_ecore_evas_obj_callback_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   Evas_Coord ow, oh, w, h;
+
+   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+   if ((w != ow) || (h != oh)) /* avoid recursion on ecore_evas_resize side */
+     ecore_evas_resize(ee, ow, oh);
+}
+
+static void
+_ecore_evas_obj_callback_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   Evas_Coord w, h;
+
+   evas_object_size_hint_min_get(obj, &w, &h);
+   ecore_evas_size_min_set(ee, w, h);
+
+   evas_object_size_hint_max_get(obj, &w, &h);
+   if (w < 1) w = -1;
+   if (h < 1) h = -1;
+   ecore_evas_size_max_set(ee, w, h);
+}
+
+static void
+_ecore_evas_obj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   _ecore_evas_object_dissociate(ee, obj);
+   ecore_evas_free(ee);
+}
+
+static void
+_ecore_evas_obj_callback_del_dissociate(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   _ecore_evas_object_dissociate(ee, obj);
+}
+
+static void
+_ecore_evas_delete_request(Ecore_Evas *ee)
+{
+   Evas_Object *obj = _ecore_evas_associate_get(ee);
+   _ecore_evas_object_dissociate(ee, obj);
+   evas_object_del(obj);
+   ecore_evas_free(ee);
+}
+
+static void
+_ecore_evas_destroy(Ecore_Evas *ee)
+{
+   Evas_Object *obj = _ecore_evas_associate_get(ee);
+   if (!obj)
+     return;
+   _ecore_evas_object_dissociate(ee, obj);
+   evas_object_del(obj);
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee)
+{
+   Evas_Object *obj = _ecore_evas_associate_get(ee);
+   Evas_Coord w, h;
+   ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+   evas_object_resize(obj, w, h);
+}
+
+static void
+_ecore_evas_pre_free(Ecore_Evas *ee)
+{
+   Evas_Object *obj = _ecore_evas_associate_get(ee);
+   if (!obj)
+     return;
+   _ecore_evas_object_dissociate(ee, obj);
+   evas_object_del(obj);
+}
+
+static int
+_ecore_evas_object_evas_check(const char *function, const Ecore_Evas *ee, const Evas_Object *obj)
+{
+   const char *name, *type;
+   Evas *e;
+
+   e = evas_object_evas_get(obj);
+   if (e == ee->evas)
+     return 1;
+
+   name = evas_object_name_get(obj);
+   type = evas_object_type_get(obj);
+
+   ERR("ERROR: %s(): object %p (name=\"%s\", type=\"%s\") evas "
+       "is not the same as this Ecore_Evas evas: %p != %p",
+       function, obj,
+       name ? name : "", type ? type : "", e, ee->evas);
+   fflush(stderr);
+   if (getenv("ECORE_ERROR_ABORT")) abort();
+
+   return 0;
+}
+
+/**
+ * Associate the given object to this ecore evas.
+ *
+ * Association means that operations on one will affect the other, for
+ * example moving the object will move the window, resize the object will
+ * also affect the ecore evas window, hide and show applies as well.
+ *
+ * This is meant to simplify development, since you often need to associate
+ * these events with your "base" objects, background or bottom-most object.
+ *
+ * Be aware that some methods might not be what you would like, deleting
+ * either the window or the object will delete the other. If you want to
+ * change that behavior, let's say to hide window when it's closed, you
+ * must use ecore_evas_callback_delete_request_set() and set your own code,
+ * like ecore_evas_hide(). Just remember that if you override delete_request
+ * and still want to delete the window/object, you must do that yourself.
+ *
+ * Since we now define delete_request, deleting windows will not quit
+ * main loop, if you wish to do so, you should listen for EVAS_CALLBACK_FREE
+ * on the object, that way you get notified and you can call
+ * ecore_main_loop_quit().
+ *
+ * Flags can be OR'ed of:
+ *   - ECORE_EVAS_OBJECT_ASSOCIATE_BASE (or 0): to listen to basic events
+ *     like delete, resize and move, but no stacking or layer are used.
+ *   - ECORE_EVAS_OBJECT_ASSOCIATE_STACK: stacking operations will act
+ *     on the Ecore_Evas, not the object. So evas_object_raise() will
+ *     call ecore_evas_raise(). Relative operations (stack_above, stack_below)
+ *     are still not implemented.
+ *   - ECORE_EVAS_OBJECT_ASSOCIATE_LAYER: stacking operations will act
+ *     on the Ecore_Evas, not the object. So evas_object_layer_set() will
+ *     call ecore_evas_layer_set().
+ *   - ECORE_EVAS_OBJECT_ASSOCIATE_DEL: the object delete will delete the
+ *     ecore_evas as well as delete_requests on the ecore_evas will delete
+ *     etc.
+ *
+ * @param ee The Ecore_Evas to associate to @a obj
+ * @param obj The object to associate to @a ee
+ * @param flags The association flags.
+ * @return 1 on success, 0 otherwise.
+ */
+EAPI int
+ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags)
+{
+   Ecore_Evas *old_ee;
+   Evas_Object *old_obj;
+
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+   {
+      ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
+      return 0;
+   }
+
+   CHECK_PARAM_POINTER_RETURN("obj", obj, 0);
+   if (!_ecore_evas_object_evas_check(__FUNCTION__, ee, obj))
+     return 0;
+
+   old_ee = _evas_object_associate_get(obj);;
+   if (old_ee)
+     ecore_evas_object_dissociate(old_ee, obj);
+
+   old_obj = _ecore_evas_associate_get(ee);
+   if (old_obj)
+     ecore_evas_object_dissociate(ee, old_obj);
+
+   _ecore_evas_object_associate(ee, obj, flags);
+   return 1;
+}
+
+/**
+ * Cancel the association set with ecore_evas_object_associate().
+ *
+ * @param ee The Ecore_Evas to dissociate from @a obj
+ * @param obj The object to dissociate from @a ee
+ * @return 1 on success, 0 otherwise.
+ */
+EAPI int
+ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj)
+{
+   Ecore_Evas *old_ee;
+   Evas_Object *old_obj;
+
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+   {
+      ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
+      return 0;
+   }
+
+   CHECK_PARAM_POINTER_RETURN("obj", obj, 0);
+   old_ee = _evas_object_associate_get(obj);
+   if (ee != old_ee) {
+      ERR("ERROR: trying to dissociate object that is not using "
+         "this Ecore_Evas: %p != %p", ee, old_ee);
+      return 0;
+   }
+
+   old_obj = _ecore_evas_associate_get(ee);
+   if (old_obj != obj) {
+      ERR("ERROR: trying to dissociate object that is not being "
+         "used by this Ecore_Evas: %p != %p", old_obj, obj);
+      return 0;
+   }
+
+   _ecore_evas_object_dissociate(ee, obj);
+
+   return 1;
+}
+
+EAPI Evas_Object *
+ecore_evas_object_associate_get(const Ecore_Evas *ee)
+{
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+   {
+      ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
+      return NULL;
+   }
+   return _ecore_evas_associate_get(ee);
+}
+
+static void
+_ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags)
+{
+   evas_object_event_callback_add
+     (obj, EVAS_CALLBACK_SHOW,
+      _ecore_evas_obj_callback_show, ee);
+   evas_object_event_callback_add
+     (obj, EVAS_CALLBACK_HIDE,
+      _ecore_evas_obj_callback_hide, ee);
+   evas_object_event_callback_add
+     (obj, EVAS_CALLBACK_RESIZE,
+      _ecore_evas_obj_callback_resize, ee);
+   evas_object_event_callback_add
+     (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+      _ecore_evas_obj_callback_changed_size_hints, ee);
+   if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_DEL)
+     evas_object_event_callback_add
+       (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del, ee);
+   else
+     evas_object_event_callback_add
+       (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del_dissociate, ee);
+
+   evas_object_intercept_move_callback_add
+     (obj, _ecore_evas_obj_intercept_move, ee);
+
+   if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_STACK)
+     {
+        evas_object_intercept_raise_callback_add
+          (obj, _ecore_evas_obj_intercept_raise, ee);
+        evas_object_intercept_lower_callback_add
+          (obj, _ecore_evas_obj_intercept_lower, ee);
+        evas_object_intercept_stack_above_callback_add
+          (obj, _ecore_evas_obj_intercept_stack_above, ee);
+        evas_object_intercept_stack_below_callback_add
+          (obj, _ecore_evas_obj_intercept_stack_below, ee);
+     }
+
+   if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_LAYER)
+     evas_object_intercept_layer_set_callback_add
+       (obj, _ecore_evas_obj_intercept_layer_set, ee);
+
+   if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_DEL)
+     {
+        ecore_evas_callback_delete_request_set(ee, _ecore_evas_delete_request);
+        ecore_evas_callback_destroy_set(ee, _ecore_evas_destroy);
+     }
+   ecore_evas_callback_pre_free_set(ee, _ecore_evas_pre_free);
+   ecore_evas_callback_resize_set(ee, _ecore_evas_resize);
+
+   _evas_object_associate_set(obj, ee);
+   _ecore_evas_associate_set(ee, obj);
+}
+
+static void
+_ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj)
+{
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_SHOW,
+      _ecore_evas_obj_callback_show, ee);
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_HIDE,
+      _ecore_evas_obj_callback_hide, ee);
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_RESIZE,
+      _ecore_evas_obj_callback_resize, ee);
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+      _ecore_evas_obj_callback_changed_size_hints, ee);
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del, ee);
+   evas_object_event_callback_del_full
+     (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del_dissociate, ee);
+
+   evas_object_intercept_move_callback_del
+     (obj, _ecore_evas_obj_intercept_move);
+
+   evas_object_intercept_raise_callback_del
+     (obj, _ecore_evas_obj_intercept_raise);
+   evas_object_intercept_lower_callback_del
+     (obj, _ecore_evas_obj_intercept_lower);
+   evas_object_intercept_stack_above_callback_del
+     (obj, _ecore_evas_obj_intercept_stack_above);
+   evas_object_intercept_stack_below_callback_del
+     (obj, _ecore_evas_obj_intercept_stack_below);
+
+   evas_object_intercept_layer_set_callback_del
+     (obj, _ecore_evas_obj_intercept_layer_set);
+
+   if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+   {
+      ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
+   }
+   else
+   {
+      if (ee->func.fn_delete_request == _ecore_evas_delete_request)
+       ecore_evas_callback_delete_request_set(ee, NULL);
+      if (ee->func.fn_destroy == _ecore_evas_destroy)
+       ecore_evas_callback_destroy_set(ee, NULL);
+      if (ee->func.fn_resize == _ecore_evas_resize)
+       ecore_evas_callback_resize_set(ee, NULL);
+      if (ee->func.fn_pre_free == _ecore_evas_pre_free)
+       ecore_evas_callback_pre_free_set(ee, NULL);
+
+      _ecore_evas_associate_del(ee);
+   }
+
+   _evas_object_associate_del(obj);
+}
+
+/**
+ * Helper ecore_getopt callback to list available Ecore_Evas engines.
+ *
+ * This will list all available engines except buffer, this is useful
+ * for applications to let user choose how they should create windows
+ * with ecore_evas_new().
+ *
+ * @c callback_data value is used as @c FILE* and says where to output
+ * messages, by default it is @c stdout. You can specify this value
+ * with ECORE_GETOPT_CALLBACK_FULL() or ECORE_GETOPT_CALLBACK_ARGS().
+ *
+ * If there is a boolean storage provided, then it is marked with 1
+ * when this option is executed.
+ */
+unsigned char
+ecore_getopt_callback_ecore_evas_list_engines(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str __UNUSED__, void *data, Ecore_Getopt_Value *storage)
+{
+   Eina_List  *lst, *n;
+   const char *engine;
+   FILE *fp = data;
+
+   if (!fp)
+     fp = stdout;
+
+   lst = ecore_evas_engines_get();
+
+   fputs("supported engines:\n", fp);
+   EINA_LIST_FOREACH(lst, n, engine)
+     if (strcmp(engine, "buffer") != 0)
+       fprintf(fp, "\t%s\n", engine);
+
+   ecore_evas_engines_free(lst);
+
+   if (storage->boolp)
+     *storage->boolp = 1;
+
+   return 1;
+}
diff --git a/src/lib/ecore_evas/ecore_evas_win32.c b/src/lib/ecore_evas/ecore_evas_win32.c
new file mode 100644 (file)
index 0000000..69ab158
--- /dev/null
@@ -0,0 +1,1266 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h> /* for NULL */
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#ifdef BUILD_ECORE_EVAS_WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+# include <Ecore_Win32.h>
+# include <ecore_win32_private.h>
+#endif /* BUILD_ECORE_EVAS_WIN32 */
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_WIN32
+
+#define ECORE_EVAS_EVENT_COUNT 8
+
+static int _ecore_evas_init_count = 0;
+
+static Ecore_Event_Handler *ecore_evas_event_handlers[ECORE_EVAS_EVENT_COUNT];
+
+static int _ecore_evas_win32_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_win32_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+/* Private functions */
+
+static int
+_ecore_evas_win32_render(Ecore_Evas *ee)
+{
+   int rend = 0;
+   Eina_List *updates = NULL;
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Eina_List *ll;
+   Ecore_Evas *ee2;
+
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+        if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+        rend |= _ecore_evas_buffer_render(ee2);
+        if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+#endif
+   if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+   if (ee->prop.avoid_damage)
+     {
+        updates = evas_render_updates(ee->evas);
+        if (updates) evas_render_updates_free(updates);
+     }
+   else if ((ee->visible) ||
+            ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
+            ((ee->should_be_visible) && (ee->prop.override)))
+     {
+        if (ee->shaped)
+          {
+             updates = evas_render_updates(ee->evas);
+             if (updates) evas_render_updates_free(updates);
+          }
+        else
+          {
+             updates = evas_render_updates(ee->evas);
+             if (updates) evas_render_updates_free(updates);
+          }
+     }
+   else
+     evas_norender(ee->evas);
+   if (updates) rend = 1;
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+   return rend;
+}
+
+static int
+_ecore_evas_win32_init(void)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1)
+     return _ecore_evas_init_count;
+   
+   ecore_evas_event_handlers[0]  = ecore_event_handler_add(ECORE_WIN32_EVENT_MOUSE_IN, _ecore_evas_win32_event_mouse_in, NULL);
+   ecore_evas_event_handlers[1]  = ecore_event_handler_add(ECORE_WIN32_EVENT_MOUSE_OUT, _ecore_evas_win32_event_mouse_out, NULL);
+   ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_DAMAGE, _ecore_evas_win32_event_window_damage, NULL);
+   ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_DESTROY, _ecore_evas_win32_event_window_destroy, NULL);
+   ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_SHOW, _ecore_evas_win32_event_window_show, NULL);
+   ecore_evas_event_handlers[5]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_HIDE, _ecore_evas_win32_event_window_hide, NULL);
+   ecore_evas_event_handlers[6]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_CONFIGURE, _ecore_evas_win32_event_window_configure, NULL);
+   ecore_evas_event_handlers[7]  = ecore_event_handler_add(ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST, _ecore_evas_win32_event_window_delete_request, NULL);
+
+   ecore_event_evas_init();
+   return _ecore_evas_init_count;
+}
+
+int
+_ecore_evas_win32_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+        int i;
+
+        for (i = 0; i < ECORE_EVAS_EVENT_COUNT; i++)
+          ecore_event_handler_del(ecore_evas_event_handlers[i]);
+        ecore_event_evas_shutdown();
+     }
+
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+
+   return _ecore_evas_init_count;
+}
+
+static int
+_ecore_evas_win32_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                 *ee;
+   Ecore_Win32_Event_Mouse_In *e;
+
+   INF("mouse in");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+
+   if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
+   /* FIXME to do */
+/*    _ecore_evas_x_modifier_locks_update(ee, e->modifiers); */
+   evas_event_feed_mouse_in(ee->evas, e->time, NULL);
+   evas_focus_in(ee->evas);
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                  *ee;
+   Ecore_Win32_Event_Mouse_Out *e;
+
+   INF("mouse out");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+
+   /* FIXME to do */
+/*    _ecore_evas_x_modifier_locks_update(ee, e->modifiers); */
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+
+   evas_event_feed_mouse_out(ee->evas, e->time, NULL);
+   if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
+   if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                      *ee;
+   Ecore_Win32_Event_Window_Damage *e;
+
+   INF("window damage");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+
+   if (ee->prop.avoid_damage)
+     {
+#ifdef _MSC_VER
+# pragma message ("[ECORE] [WIN32] No Region code")
+#else
+# warning [ECORE] [WIN32] No Region code
+#endif /* ! _MSC_VER */
+     }
+   else
+     {
+        if (ee->rotation == 0)
+          evas_damage_rectangle_add(ee->evas,
+                                    e->x,
+                                    e->y,
+                                    e->width,
+                                    e->height);
+        else if (ee->rotation == 90)
+          evas_damage_rectangle_add(ee->evas,
+                                    ee->h - e->y - e->height,
+                                    e->x,
+                                    e->height,
+                                    e->width);
+        else if (ee->rotation == 180)
+          evas_damage_rectangle_add(ee->evas,
+                                    ee->w - e->x - e->width,
+                                    ee->h - e->y - e->height,
+                                    e->width,
+                                    e->height);
+        else if (ee->rotation == 270)
+          evas_damage_rectangle_add(ee->evas,
+                                    e->y,
+                                    ee->w - e->x - e->width,
+                                    e->height,
+                                    e->width);
+     }
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                       *ee;
+   Ecore_Win32_Event_Window_Destroy *e;
+
+   INF("window destroy");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+   if (ee->func.fn_destroy) ee->func.fn_destroy(ee);
+   ecore_evas_free(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                    *ee;
+   Ecore_Win32_Event_Window_Show *e;
+
+   INF("window show");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+   if (ee->visible) return 0; /* dont pass it on */
+   ee->visible = 1;
+   if (ee->func.fn_show) ee->func.fn_show(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                    *ee;
+   Ecore_Win32_Event_Window_Hide *e;
+
+   INF("window hide");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+   if (!ee->visible) return 0; /* dont pass it on */
+   ee->visible = 0;
+   if (ee->func.fn_hide) ee->func.fn_hide(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                         *ee;
+   Ecore_Win32_Event_Window_Configure *e;
+
+   INF("window configure");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+
+   if ((ee->x != e->x) || (ee->y != e->y))
+     {
+        ee->x = e->x;
+        ee->y = e->y;
+        if (ee->func.fn_move) ee->func.fn_move(ee);
+     }
+
+   if ((ee->w != e->width) || (ee->h != e->height))
+     {
+        ee->w = e->width;
+        ee->h = e->height;
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          {
+             evas_output_size_set(ee->evas, ee->h, ee->w);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+          }
+        else
+          {
+             evas_output_size_set(ee->evas, ee->w, ee->h);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+          }
+        if (ee->prop.avoid_damage)
+          {
+             ecore_evas_avoid_damage_set(ee, 0);
+             ecore_evas_avoid_damage_set(ee, 1);
+          }
+        /* FIXME: to do... */
+/*        if (ee->shaped) */
+/*          _ecore_evas_x_resize_shape(ee); */
+        if ((ee->expecting_resize.w > 0) &&
+            (ee->expecting_resize.h > 0))
+          {
+             if ((ee->expecting_resize.w == ee->w) &&
+                 (ee->expecting_resize.h == ee->h))
+               _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                              ecore_win32_current_time_get());
+             ee->expecting_resize.w = 0;
+             ee->expecting_resize.h = 0;
+          }
+        if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+
+   return 1;
+}
+
+static int
+_ecore_evas_win32_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                              *ee;
+   Ecore_Win32_Event_Window_Delete_Request *e;
+
+   INF("window delete request");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if ((Ecore_Window)e->window != ee->prop.window) return 1;
+   if (ee->func.fn_delete_request) ee->func.fn_delete_request(ee);
+
+   INF(" * ee event delete\n");
+   return 1;
+}
+
+
+/* Ecore_Evas interface */
+
+static void
+_ecore_evas_win32_free(Ecore_Evas *ee)
+{
+   INF("ecore evas free");
+
+   ecore_win32_window_free((struct _Ecore_Win32_Window *)ee->prop.window);
+   ecore_event_window_unregister(ee->prop.window);
+   _ecore_evas_win32_shutdown();
+   ecore_win32_shutdown();
+}
+
+static void
+_ecore_evas_win32_callback_delete_request_set(Ecore_Evas *ee,
+                                              void (*func) (Ecore_Evas *ee))
+{
+   ee->func.fn_delete_request = func;
+}
+
+static void
+_ecore_evas_win32_move(Ecore_Evas *ee, int x, int y)
+{
+  INF("ecore evas move (%dx%d)", x, y);
+
+   if ((x != ee->x) || (y != ee->y))
+     {
+        ee->x = x;
+        ee->y = y;
+        ecore_win32_window_move((struct _Ecore_Win32_Window *)ee->prop.window,
+                                x, y);
+        if (ee->func.fn_move) ee->func.fn_move(ee);
+     }
+}
+
+static void
+_ecore_evas_win32_resize(Ecore_Evas *ee, int width, int height)
+{
+   INF("ecore evas resize (%dx%d)", width, height);
+
+   if ((ee->w != width) || (ee->h != height))
+     {
+        ee->w = width;
+        ee->h = height;
+        ecore_win32_window_resize((struct _Ecore_Win32_Window *)ee->prop.window,
+                                  width, height);
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          {
+             evas_output_size_set(ee->evas, ee->h, ee->w);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+          }
+        else
+          {
+             evas_output_size_set(ee->evas, ee->w, ee->h);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+          }
+        /* FIXME: damage and shape */
+
+        if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+}
+
+static void
+_ecore_evas_win32_move_resize(Ecore_Evas *ee, int x, int y, int width, int height)
+{
+   INF("ecore evas resize (%dx%d %dx%d)", x, y, width, height);
+
+   if ((ee->w != width) || (ee->h != height) || (x != ee->x) || (y != ee->y))
+     {
+        int change_size = 0;
+        int change_pos = 0;
+
+        if ((ee->w != width) || (ee->h != height)) change_size = 1;
+        if ((x != ee->x) || (y != ee->y)) change_pos = 1;
+
+        ee->x = x;
+        ee->y = y;
+        ee->w = width;
+        ee->h = height;
+        ecore_win32_window_move_resize((struct _Ecore_Win32_Window *)ee->prop.window,
+                                       x, y, width, height);
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          {
+             evas_output_size_set(ee->evas, ee->h, ee->w);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+          }
+        else
+          {
+             evas_output_size_set(ee->evas, ee->w, ee->h);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+          }
+        /* FIXME: damage and shape */
+        if (change_pos)
+          {
+             if (ee->func.fn_move) ee->func.fn_move(ee);
+          }
+        if (change_size)
+          {
+             if (ee->func.fn_resize) ee->func.fn_resize(ee);
+          }
+     }
+}
+
+static void
+_ecore_evas_win32_rotation_set_internal(Ecore_Evas *ee, int rotation)
+{
+   int rot_dif;
+
+   rot_dif = ee->rotation - rotation;
+   if (rot_dif < 0) rot_dif = -rot_dif;
+
+   if (rot_dif != 180)
+     {
+        int minw, minh, maxw, maxh, basew, baseh, stepw, steph;
+
+        if (!ee->prop.fullscreen)
+          {
+             ecore_win32_window_resize((struct _Ecore_Win32_Window *)ee->prop.window,
+                                       ee->h, ee->w);
+             ee->expecting_resize.w = ee->h;
+             ee->expecting_resize.h = ee->w;
+          }
+        else
+          {
+             int w, h;
+
+             ecore_win32_window_size_get((struct _Ecore_Win32_Window *)ee->prop.window,
+                                         &w, &h);
+             ecore_win32_window_resize((struct _Ecore_Win32_Window *)ee->prop.window,
+                                       h, w);
+             if ((rotation == 0) || (rotation == 180))
+               {
+                  evas_output_size_set(ee->evas, ee->w, ee->h);
+                  evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+               }
+             else
+               {
+                  evas_output_size_set(ee->evas, ee->h, ee->w);
+                  evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+               }
+             if (ee->func.fn_resize) ee->func.fn_resize(ee);
+          }
+        ecore_evas_size_min_get(ee, &minw, &minh);
+        ecore_evas_size_max_get(ee, &maxw, &maxh);
+        ecore_evas_size_base_get(ee, &basew, &baseh);
+        ecore_evas_size_step_get(ee, &stepw, &steph);
+        ee->rotation = rotation;
+        ecore_evas_size_min_set(ee, minh, minw);
+        ecore_evas_size_max_set(ee, maxh, maxw);
+        ecore_evas_size_base_set(ee, baseh, basew);
+        ecore_evas_size_step_set(ee, steph, stepw);
+        _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                       ecore_win32_current_time_get());
+     }
+   else
+     {
+        ee->rotation = rotation;
+        _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                       ecore_win32_current_time_get());
+        if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+
+   if ((ee->rotation == 90) || (ee->rotation == 270))
+     evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+   else
+     evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+}
+
+static void
+_ecore_evas_win32_rotation_set(Ecore_Evas *ee, int rotation, int resize)
+{
+   INF("ecore evas rotation: %s", rotation ? "yes" : "no");
+
+   if (ee->rotation == rotation) return;
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+   if (!strcmp(ee->driver, "software_gdi"))
+     {
+        Evas_Engine_Info_Software_Gdi *einfo;
+
+        einfo = (Evas_Engine_Info_Software_Gdi *)evas_engine_info_get(ee->evas);
+        if (!einfo) return;
+        einfo->info.rotation = rotation;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+        _ecore_evas_win32_rotation_set_internal(ee, rotation);
+     }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_GDI */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+   if (!strcmp(ee->driver, "software_ddraw"))
+     {
+        Evas_Engine_Info_Software_DDraw *einfo;
+
+        einfo = (Evas_Engine_Info_Software_DDraw *)evas_engine_info_get(ee->evas);
+        if (!einfo) return;
+        einfo->info.rotation = rotation;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+        _ecore_evas_win32_rotation_set_internal(ee, rotation);
+     }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_DDRAW */
+}
+
+static void
+_ecore_evas_win32_show(Ecore_Evas *ee)
+{
+   INF("ecore evas show");
+
+   ee->should_be_visible = 1;
+   if (ee->prop.avoid_damage)
+     _ecore_evas_win32_render(ee);
+   ecore_win32_window_show((struct _Ecore_Win32_Window *)ee->prop.window);
+/*    if (ee->prop.fullscreen) */
+/*      ecore_win32_window_focus(ee->prop.window); */
+}
+
+static void
+_ecore_evas_win32_hide(Ecore_Evas *ee)
+{
+   INF("ecore evas hide");
+
+   ecore_win32_window_hide((struct _Ecore_Win32_Window *)ee->prop.window);
+   ee->should_be_visible = 0;
+}
+
+static void
+_ecore_evas_win32_raise(Ecore_Evas *ee)
+{
+   INF("ecore evas raise");
+
+   if (!ee->prop.fullscreen)
+     ecore_win32_window_raise((struct _Ecore_Win32_Window *)ee->prop.window);
+   else
+     ecore_win32_window_raise((struct _Ecore_Win32_Window *)ee->prop.window);
+}
+
+static void
+_ecore_evas_win32_lower(Ecore_Evas *ee)
+{
+   INF("ecore evas lower");
+
+   if (!ee->prop.fullscreen)
+     ecore_win32_window_lower((struct _Ecore_Win32_Window *)ee->prop.window);
+   else
+     ecore_win32_window_lower((struct _Ecore_Win32_Window *)ee->prop.window);
+}
+
+static void
+_ecore_evas_win32_activate(Ecore_Evas *ee)
+{
+   INF("ecore evas activate");
+
+   ecore_win32_window_focus_set((struct _Ecore_Win32_Window *)ee->prop.window);
+}
+
+static void
+_ecore_evas_win32_title_set(Ecore_Evas *ee, const char *title)
+{
+   INF("ecore evas title set");
+
+   if (ee->prop.title) free(ee->prop.title);
+   ee->prop.title = NULL;
+   if (title) ee->prop.title = strdup(title);
+   ecore_win32_window_title_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                ee->prop.title);
+}
+
+static void
+_ecore_evas_win32_size_min_set(Ecore_Evas *ee, int width, int height)
+{
+   if (width < 0) width = 0;
+   if (height < 0) height = 0;
+   if ((ee->prop.min.w == width) && (ee->prop.min.h == height)) return;
+   ee->prop.min.w = width;
+   ee->prop.min.h = height;
+   ecore_win32_window_size_min_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                   width, height);
+}
+
+static void
+_ecore_evas_win32_size_max_set(Ecore_Evas *ee, int width, int height)
+{
+   if (width < 0) width = 0;
+   if (height < 0) height = 0;
+   if ((ee->prop.max.w == width) && (ee->prop.max.h == height)) return;
+   ee->prop.max.w = width;
+   ee->prop.max.h = height;
+   ecore_win32_window_size_max_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                   width, height);
+}
+
+static void
+_ecore_evas_win32_size_base_set(Ecore_Evas *ee, int width, int height)
+{
+   if (width < 0) width = 0;
+   if (height < 0) height = 0;
+   if ((ee->prop.base.w == width) && (ee->prop.base.h == height)) return;
+   ee->prop.base.w = width;
+   ee->prop.base.h = height;
+   ecore_win32_window_size_base_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                    width, height);
+}
+
+static void
+_ecore_evas_win32_size_step_set(Ecore_Evas *ee, int width, int height)
+{
+   if (width < 1) width = 1;
+   if (height < 1) height = 1;
+   if ((ee->prop.step.w == width) && (ee->prop.step.h == height)) return;
+   ee->prop.step.w = width;
+   ee->prop.step.h = height;
+   ecore_win32_window_size_step_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                    width, height);
+}
+
+static void
+_ecore_evas_win32_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+#if 0
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+        ee->prop.cursor.object = NULL;
+        ee->prop.cursor.layer = 0;
+        ee->prop.cursor.hot.x = 0;
+        ee->prop.cursor.hot.y = 0;
+        ecore_win32_window_cursor_show(ee->prop.window, 1);
+        return;
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+
+   ecore_win32_window_cursor_show(ee->prop.window, 0);
+
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                    x - ee->prop.cursor.hot.x,
+                    y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+#endif
+}
+
+static void
+_ecore_evas_win32_focus_set(Ecore_Evas *ee, int on __UNUSED__)
+{
+   ecore_win32_window_focus_set((struct _Ecore_Win32_Window *)ee->prop.window);
+}
+
+static void
+_ecore_evas_win32_iconified_set(Ecore_Evas *ee, int on)
+{
+/*    if (((ee->prop.borderless) && (on)) || */
+/*        ((!ee->prop.borderless) && (!on))) return; */
+   ee->prop.iconified = on;
+   ecore_win32_window_iconified_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                    ee->prop.iconified);
+}
+
+static void
+_ecore_evas_win32_borderless_set(Ecore_Evas *ee, int on)
+{
+   if (((ee->prop.borderless) && (on)) ||
+       ((!ee->prop.borderless) && (!on))) return;
+   ee->prop.borderless = on;
+   ecore_win32_window_borderless_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                     ee->prop.borderless);
+}
+
+static void
+_ecore_evas_win32_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   struct _Ecore_Win32_Window *window;
+
+   INF("ecore evas fullscreen set");
+
+   if ((ee->engine.win32.state.fullscreen && on) ||
+      (!ee->engine.win32.state.fullscreen && !on))
+     return;
+
+   ee->engine.win32.state.fullscreen = on;
+   ee->prop.fullscreen = on;
+
+   window = (struct _Ecore_Win32_Window *)ee->prop.window;
+
+   if (on != 0)
+   {
+      ecore_win32_window_shape_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                   0, 0, NULL);
+      ecore_win32_window_fullscreen_set((struct _Ecore_Win32_Window *)ee->prop.window,
+                                        on);
+   }
+   else
+   {
+      ecore_win32_window_fullscreen_set(window, on);
+      ecore_win32_window_shape_set(window,
+                                   window->shape.width,
+                                   window->shape.height,
+                                   window->shape.mask);
+   }
+
+   /* Nothing to be done for the GDI backend at the evas level */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWRE_DDRAW
+   if (strcmp(ee->driver, "software_ddraw") == 0)
+     {
+        Evas_Engine_Info_Software_DDraw *einfo;
+
+        einfo = (Evas_Engine_Info_Software_DDraw *)evas_engine_info_get(ecore_evas_get(ee));
+        if (einfo != NULL)
+          {
+             einfo->info.fullscreen = !!on;
+/*           einfo->info.layered = window->shape.layered; */
+             evas_engine_info_set(ecore_evas_get(ee), (Evas_Engine_Info *)einfo);
+          }
+     }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_DDRAW */
+
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+   if (strcmp(ee->driver, "direct3d") == 0)
+     {
+        Evas_Engine_Info_Direct3D *einfo;
+
+        einfo = (Evas_Engine_Info_Direct3D *)evas_engine_info_get(ecore_evas_get(ee));
+        if (einfo != NULL)
+          {
+             einfo->info.fullscreen = !!on;
+             einfo->info.layered = window->shape.layered;
+             evas_engine_info_set(ecore_evas_get(ee), (Evas_Engine_Info *)einfo);
+          }
+     }
+#endif /* BUILD_ECORE_EVAS_DIRECT3D */
+}
+
+
+static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
+{
+   _ecore_evas_win32_free,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_win32_callback_delete_request_set,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_win32_move,
+     NULL,
+     _ecore_evas_win32_resize,
+     _ecore_evas_win32_move_resize,
+     _ecore_evas_win32_rotation_set,
+     NULL, /* _ecore_evas_x_shaped_set */
+     _ecore_evas_win32_show,
+     _ecore_evas_win32_hide,
+     _ecore_evas_win32_raise,
+     _ecore_evas_win32_lower,
+     _ecore_evas_win32_activate,
+     _ecore_evas_win32_title_set,
+     NULL, /* _ecore_evas_x_name_class_set */
+     _ecore_evas_win32_size_min_set,
+     _ecore_evas_win32_size_max_set,
+     _ecore_evas_win32_size_base_set,
+     _ecore_evas_win32_size_step_set,
+     _ecore_evas_win32_cursor_set,
+     NULL, /* _ecore_evas_x_layer_set */
+     _ecore_evas_win32_focus_set,
+     _ecore_evas_win32_iconified_set,
+     _ecore_evas_win32_borderless_set,
+     NULL, /* _ecore_evas_x_override_set */
+     NULL,
+     _ecore_evas_win32_fullscreen_set,
+     NULL, /* _ecore_evas_x_avoid_damage_set */
+     NULL, /* _ecore_evas_x_withdrawn_set */
+     NULL, /* _ecore_evas_x_sticky_set */
+     NULL, /* _ecore_evas_x_ignore_events_set */
+     NULL,  /* _ecore_evas_x_alpha_set */
+     NULL, //transparent
+     
+     NULL // render
+};
+
+#endif /* BUILD_ECORE_EVAS_WIN32 */
+
+/* API */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+static int
+_ecore_evas_engine_software_gdi_init(Ecore_Evas *ee)
+{
+   Evas_Engine_Info_Software_Gdi *einfo;
+   const char                    *driver;
+   int                            rmethod;
+
+   driver = "software_gdi";
+
+   rmethod = evas_render_method_lookup(driver);
+   if (!rmethod)
+     return 0;
+
+   ee->driver = driver;
+   evas_output_method_set(ee->evas, rmethod);
+
+   einfo = (Evas_Engine_Info_Software_Gdi *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_Win32_Window *)ee->prop.window)->window;
+        einfo->info.mask = NULL;
+        einfo->info.depth = ecore_win32_screen_depth_get();
+        einfo->info.rotation = 0;
+        einfo->info.fullscreen = 0;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+
+   return 1;
+}
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_GDI */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+static int
+_ecore_evas_engine_software_ddraw_init(Ecore_Evas *ee)
+{
+   Evas_Engine_Info_Software_DDraw *einfo;
+   const char                      *driver;
+   int                              rmethod;
+
+   driver = "software_ddraw";
+
+   rmethod = evas_render_method_lookup(driver);
+   if (!rmethod)
+     return 0;
+
+   ee->driver = driver;
+   evas_output_method_set(ee->evas, rmethod);
+
+   einfo = (Evas_Engine_Info_Software_DDraw *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_Win32_Window *)ee->prop.window)->window;
+        einfo->info.depth = ecore_win32_screen_depth_get();
+        einfo->info.rotation = 0;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+
+   return 1;
+}
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_DDRAW */
+
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+static int
+_ecore_evas_engine_direct3d_init(Ecore_Evas *ee)
+{
+   Evas_Engine_Info_Direct3D *einfo;
+   const char                *driver;
+   int                        rmethod;
+
+   driver = "direct3d";
+
+   rmethod = evas_render_method_lookup(driver);
+   if (!rmethod)
+     return 0;
+
+   ee->driver = driver;
+   evas_output_method_set(ee->evas, rmethod);
+
+   einfo = (Evas_Engine_Info_Direct3D *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_Win32_Window *)ee->prop.window)->window;
+        einfo->info.depth = ecore_win32_screen_depth_get();
+        einfo->info.rotation = 0;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+
+   return 1;
+}
+#endif /* BUILD_ECORE_EVAS_DIRECT3D */
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+static int
+_ecore_evas_engine_opengl_glew_init(Ecore_Evas *ee)
+{
+   Evas_Engine_Info_GL_Glew *einfo;
+   const char               *driver;
+   int                       rmethod;
+
+   driver = "gl_glew";
+
+   rmethod = evas_render_method_lookup(driver);
+   if (!rmethod)
+     return 0;
+
+   ee->driver = driver;
+   evas_output_method_set(ee->evas, rmethod);
+
+   einfo = (Evas_Engine_Info_GL_Glew *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_Win32_Window *)ee->prop.window)->window;
+        einfo->info.depth = ecore_win32_screen_depth_get();
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+
+   return 1;
+}
+#endif /* BUILD_ECORE_EVAS_OPENGL_GLEW */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+static int
+_ecore_evas_engine_software_16_ddraw_init(Ecore_Evas *ee)
+{
+   Evas_Engine_Info_Software_DDraw *einfo;
+   const char                      *driver;
+   int                              rmethod;
+
+   driver = "software_16_ddraw";
+
+   rmethod = evas_render_method_lookup(driver);
+   if (!rmethod)
+     return 0;
+
+   ee->driver = driver;
+   evas_output_method_set(ee->evas, rmethod);
+
+   if (ecore_win32_screen_depth_get() != 16)
+     return 0;
+
+   einfo = (Evas_Engine_Info_Software_16_DDraw *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_Win32_Window *)ee->prop.window)->window;
+        einfo->info.depth = ecore_win32_screen_depth_get();
+        einfo->info.rotation = 0;
+        evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+     }
+
+   return 1;
+}
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW */
+
+#ifdef BUILD_ECORE_EVAS_WIN32
+static Ecore_Evas *
+_ecore_evas_win32_new_internal(int (*_ecore_evas_engine_init)(Ecore_Evas *ee),
+                               Ecore_Win32_Window *parent,
+                               int                 x,
+                               int                 y,
+                               int                 width,
+                               int                 height)
+{
+   Ecore_Evas *ee;
+
+   if (!ecore_win32_init())
+     return NULL;
+
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee)
+     return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_win32_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_win32_engine_func;
+
+   if (width < 1) width = 1;
+   if (height < 1) height = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = width;
+   ee->h = height;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   /* FIXME: sticky to add */
+   ee->prop.window = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_size_set(ee->evas, width, height);
+   evas_output_viewport_set(ee->evas, 0, 0, width, height);
+
+   ee->engine.win32.parent = parent;
+   ee->prop.window = (Ecore_Window)ecore_win32_window_new(parent, x, y, width, height);
+   if (!ee->prop.window)
+     {
+        _ecore_evas_win32_shutdown();
+        free(ee);
+        return NULL;
+     }
+
+   if (!_ecore_evas_engine_init(ee))
+     {
+        _ecore_evas_win32_shutdown();
+        free(ee);
+        return NULL;
+     }
+
+   ee->engine.func->fn_render = _ecore_evas_win32_render;
+   _ecore_evas_register(ee);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, _ecore_evas_mouse_move_process);
+   
+   return ee;
+}
+
+#endif /* BUILD_ECORE_EVAS_WIN32 */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
+
+EAPI Ecore_Evas *
+ecore_evas_software_gdi_new(Ecore_Win32_Window *parent,
+                            int                 x,
+                            int                 y,
+                            int                 width,
+                            int                 height)
+{
+   return _ecore_evas_win32_new_internal(_ecore_evas_engine_software_gdi_init,
+                                         parent,
+                                         x,
+                                         y,
+                                         width,
+                                         height);
+}
+
+#else
+
+EAPI Ecore_Evas *
+ecore_evas_software_gdi_new(Ecore_Win32_Window *parent __UNUSED__,
+                            int                 x __UNUSED__,
+                            int                 y __UNUSED__,
+                            int                 width __UNUSED__,
+                            int                 height __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_GDI */
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW
+
+EAPI Ecore_Evas *
+ecore_evas_software_ddraw_new(Ecore_Win32_Window *parent,
+                              int                 x,
+                              int                 y,
+                              int                 width,
+                              int                 height)
+{
+   return _ecore_evas_win32_new_internal(_ecore_evas_engine_software_ddraw_init,
+                                         parent,
+                                         x,
+                                         y,
+                                         width,
+                                         height);
+}
+
+#else
+
+EAPI Ecore_Evas *
+ecore_evas_software_ddraw_new(Ecore_Win32_Window *parent __UNUSED__,
+                              int                 x __UNUSED__,
+                              int                 y __UNUSED__,
+                              int                 width __UNUSED__,
+                              int                 height __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_DDRAW */
+
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW
+
+EAPI Ecore_Evas *
+ecore_evas_software_16_ddraw_new(Ecore_Win32_Window *parent,
+                                 int                 x,
+                                 int                 y,
+                                 int                 width,
+                                 int                 height)
+{
+   return _ecore_evas_win32_new_internal(_ecore_evas_engine_software_16_ddraw_init,
+                                         parent,
+                                         x,
+                                         y,
+                                         width,
+                                         height);
+}
+
+#else
+
+EAPI Ecore_Evas *
+ecore_evas_software_16_ddraw_new(Ecore_Win32_Window *parent __UNUSED__,
+                                 int                 x __UNUSED__,
+                                 int                 y __UNUSED__,
+                                 int                 width __UNUSED__,
+                                 int                 height __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW */
+
+
+#ifdef BUILD_ECORE_EVAS_DIRECT3D
+
+EAPI Ecore_Evas *
+ecore_evas_direct3d_new(Ecore_Win32_Window *parent,
+                        int                 x,
+                        int                 y,
+                        int                 width,
+                        int                 height)
+{
+   return _ecore_evas_win32_new_internal(_ecore_evas_engine_direct3d_init,
+                                         parent,
+                                         x,
+                                         y,
+                                         width,
+                                         height);
+}
+
+#else
+
+EAPI Ecore_Evas *
+ecore_evas_direct3d_new(Ecore_Win32_Window *parent __UNUSED__,
+                        int                 x __UNUSED__,
+                        int                 y __UNUSED__,
+                        int                 width __UNUSED__,
+                        int                 height __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* ! BUILD_ECORE_EVAS_DIRECT3D */
+
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_GLEW
+
+EAPI Ecore_Evas *
+ecore_evas_gl_glew_new(Ecore_Win32_Window *parent,
+                       int                 x,
+                       int                 y,
+                       int                 width,
+                       int                 height)
+{
+   return _ecore_evas_win32_new_internal(_ecore_evas_engine_opengl_glew_init,
+                                         parent,
+                                         x,
+                                         y,
+                                         width,
+                                         height);
+}
+
+#else
+
+EAPI Ecore_Evas *
+ecore_evas_gl_glew_new(Ecore_Win32_Window *parent __UNUSED__,
+                       int                 x __UNUSED__,
+                       int                 y __UNUSED__,
+                       int                 width __UNUSED__,
+                       int                 height __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* BUILD_ECORE_EVAS_OPENGL_GLEW */
+
+
+#ifdef BUILD_ECORE_EVAS_WIN32
+
+EAPI Ecore_Win32_Window *
+ecore_evas_win32_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_Win32_Window *) ecore_evas_window_get(ee);
+}
+
+#else
+
+EAPI Ecore_Win32_Window *
+ecore_evas_win32_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* BUILD_ECORE_EVAS_WIN32 */
diff --git a/src/lib/ecore_evas/ecore_evas_wince.c b/src/lib/ecore_evas/ecore_evas_wince.c
new file mode 100644 (file)
index 0000000..d283302
--- /dev/null
@@ -0,0 +1,910 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h> /* for NULL */
+
+#include <Ecore.h>
+#include "ecore_private.h"
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+# include <Ecore_WinCE.h>
+# include <ecore_wince_private.h>
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_WINCE */
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+
+#define ECORE_EVAS_EVENT_COUNT 7
+
+static int _ecore_evas_init_count = 0;
+
+static Ecore_Event_Handler *ecore_evas_event_handlers[ECORE_EVAS_EVENT_COUNT];
+
+static int _ecore_evas_wince_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+static int _ecore_evas_wince_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+/* Private functions */
+
+static int
+_ecore_evas_wince_render(Ecore_Evas *ee)
+{
+   int rend = 0;
+   Eina_List *updates = NULL;
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Eina_List *ll;
+   Ecore_Evas *ee2;
+
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+       if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+       rend |= _ecore_evas_buffer_render(ee2);
+       if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+#endif
+   if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+   if (ee->prop.avoid_damage)
+     {
+        updates = evas_render_updates(ee->evas);
+        if (updates) evas_render_updates_free(updates);
+     }
+   else if ((ee->visible) ||
+            ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
+            ((ee->should_be_visible) && (ee->prop.override)))
+     {
+        if (ee->shaped)
+          {
+             updates = evas_render_updates(ee->evas);
+             if (updates) evas_render_updates_free(updates);
+          }
+        else
+          {
+             updates = evas_render_updates(ee->evas);
+             if (updates) evas_render_updates_free(updates);
+          }
+     }
+   else
+     evas_norender(ee->evas);
+   if (updates) rend = 1;
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+   return rend;
+}
+
+static int
+_ecore_evas_wince_init(void)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1)
+     return _ecore_evas_init_count;
+   
+   ecore_evas_event_handlers[0]  = ecore_event_handler_add(ECORE_WINCE_EVENT_MOUSE_IN, _ecore_evas_wince_event_mouse_in, NULL);
+   ecore_evas_event_handlers[1]  = ecore_event_handler_add(ECORE_WINCE_EVENT_MOUSE_OUT, _ecore_evas_wince_event_mouse_out, NULL);
+   ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_WINCE_EVENT_WINDOW_DAMAGE, _ecore_evas_wince_event_window_damage, NULL);
+   ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_WINCE_EVENT_WINDOW_DESTROY, _ecore_evas_wince_event_window_destroy, NULL);
+   ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_WINCE_EVENT_WINDOW_SHOW, _ecore_evas_wince_event_window_show, NULL);
+   ecore_evas_event_handlers[5]  = ecore_event_handler_add(ECORE_WINCE_EVENT_WINDOW_HIDE, _ecore_evas_wince_event_window_hide, NULL);
+   ecore_evas_event_handlers[6]  = ecore_event_handler_add(ECORE_WINCE_EVENT_WINDOW_DELETE_REQUEST, _ecore_evas_wince_event_window_delete_request, NULL);
+
+   ecore_event_evas_init();
+   return _ecore_evas_init_count;
+}
+
+int
+_ecore_evas_wince_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+       int i;
+
+       for (i = 0; i < ECORE_EVAS_EVENT_COUNT; i++)
+         ecore_event_handler_del(ecore_evas_event_handlers[i]);
+        ecore_event_evas_shutdown();
+     }
+
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+
+   return _ecore_evas_init_count;
+}
+
+static int
+_ecore_evas_wince_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                 *ee;
+   Ecore_WinCE_Event_Mouse_In *e;
+
+   INF("mouse in");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+
+   if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
+   /* FIXME to do */
+/*    _ecore_evas_x_modifier_locks_update(ee, e->modifiers); */
+   evas_event_feed_mouse_in(ee->evas, e->time, NULL);
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                  *ee;
+   Ecore_WinCE_Event_Mouse_Out *e;
+
+   INF("mouse out");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+
+   /* FIXME to do */
+/*    _ecore_evas_x_modifier_locks_update(ee, e->modifiers); */
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+
+   evas_event_feed_mouse_out(ee->evas, e->time, NULL);
+   if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
+   if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                      *ee;
+   Ecore_WinCE_Event_Window_Damage *e;
+
+   INF("window damage");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+
+   if (ee->prop.avoid_damage)
+     {
+#warning [ECORE] [WINCE] No Region code
+     }
+   else
+     {
+        if (ee->rotation == 0)
+          evas_damage_rectangle_add(ee->evas,
+                                    e->x,
+                                    e->y,
+                                    e->width,
+                                    e->height);
+        else if (ee->rotation == 90)
+          evas_damage_rectangle_add(ee->evas,
+                                    ee->h - e->y - e->height,
+                                    e->x,
+                                    e->height,
+                                    e->width);
+        else if (ee->rotation == 180)
+          evas_damage_rectangle_add(ee->evas,
+                                    ee->w - e->x - e->width,
+                                    ee->h - e->y - e->height,
+                                    e->width,
+                                    e->height);
+        else if (ee->rotation == 270)
+          evas_damage_rectangle_add(ee->evas,
+                                    e->y,
+                                    ee->w - e->x - e->width,
+                                    e->height,
+                                    e->width);
+     }
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                       *ee;
+   Ecore_WinCE_Event_Window_Destroy *e;
+
+   INF("window destroy");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+   if (ee->func.fn_destroy) ee->func.fn_destroy(ee);
+   ecore_evas_free(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                    *ee;
+   Ecore_WinCE_Event_Window_Show *e;
+
+   INF("window show");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+   if (ee->visible) return 0; /* dont pass it on */
+   ee->visible = 1;
+   if (ee->func.fn_show) ee->func.fn_show(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                    *ee;
+   Ecore_WinCE_Event_Window_Hide *e;
+
+   INF("window hide");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+   if (!ee->visible) return 0; /* dont pass it on */
+   ee->visible = 0;
+   if (ee->func.fn_hide) ee->func.fn_hide(ee);
+
+   return 1;
+}
+
+static int
+_ecore_evas_wince_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas                              *ee;
+   Ecore_WinCE_Event_Window_Delete_Request *e;
+
+   INF("window delete request");
+
+   e = event;
+   ee = ecore_event_window_match((Ecore_Window)e->window);
+   if (!ee) return 1; /* pass on event */
+   if (e->window != (Ecore_WinCE_Window *)ee->prop.window) return 1;
+   if (ee->func.fn_delete_request) ee->func.fn_delete_request(ee);
+
+   return 1;
+}
+
+
+/* Ecore_Evas interface */
+
+static void
+_ecore_evas_wince_free(Ecore_Evas *ee)
+{
+   INF("ecore evas free");
+
+   ecore_wince_window_free((Ecore_WinCE_Window *)ee->prop.window);
+   ecore_event_window_unregister(ee->prop.window);
+   _ecore_evas_wince_shutdown();
+   ecore_wince_shutdown();
+}
+
+static void
+_ecore_evas_wince_callback_delete_request_set(Ecore_Evas *ee,
+                                              void (*func) (Ecore_Evas *ee))
+{
+   ee->func.fn_delete_request = func;
+}
+
+static void
+_ecore_evas_wince_move(Ecore_Evas *ee, int x, int y)
+{
+  INF("ecore evas move (%dx%d)", x, y);
+
+   if ((x != ee->x) || (y != ee->y))
+     {
+        ee->x = x;
+        ee->y = y;
+        ecore_wince_window_move((Ecore_WinCE_Window *)ee->prop.window, x, y);
+        if (ee->func.fn_move) ee->func.fn_move(ee);
+     }
+}
+
+static void
+_ecore_evas_wince_resize(Ecore_Evas *ee, int width, int height)
+{
+   INF("ecore evas resize (%dx%d)", width, height);
+
+   if ((ee->w != width) || (ee->h != height))
+     {
+        ee->w = width;
+        ee->h = height;
+        ecore_wince_window_resize((Ecore_WinCE_Window *)ee->prop.window, width, height);
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          {
+             evas_output_size_set(ee->evas, ee->h, ee->w);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+          }
+        else
+          {
+             evas_output_size_set(ee->evas, ee->w, ee->h);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+          }
+        /* FIXME: damage and shape */
+
+        if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+}
+
+static void
+_ecore_evas_wince_move_resize(Ecore_Evas *ee, int x, int y, int width, int height)
+{
+   INF("ecore evas resize (%dx%d %dx%d)", x, y, width, height);
+
+   if ((ee->w != width) || (ee->h != height) || (x != ee->x) || (y != ee->y))
+     {
+        int change_size = 0;
+        int change_pos = 0;
+
+        if ((ee->w != width) || (ee->h != height)) change_size = 1;
+        if ((x != ee->x) || (y != ee->y)) change_pos = 1;
+
+        ee->x = x;
+        ee->y = y;
+        ee->w = width;
+        ee->h = height;
+        ecore_wince_window_move_resize((Ecore_WinCE_Window *)ee->prop.window, x, y, width, height);
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          {
+             evas_output_size_set(ee->evas, ee->h, ee->w);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+          }
+        else
+          {
+             evas_output_size_set(ee->evas, ee->w, ee->h);
+             evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+          }
+        /* FIXME: damage and shape */
+        if (change_pos)
+          {
+             if (ee->func.fn_move) ee->func.fn_move(ee);
+          }
+        if (change_size)
+          {
+             if (ee->func.fn_resize) ee->func.fn_resize(ee);
+          }
+     }
+}
+
+/* static void */
+/* _ecore_evas_wince_rotation_set(Ecore_Evas *ee, int rotation) */
+/* { */
+/*    int rot_dif; */
+
+/*    if (ee->rotation == rotation) return; */
+/*    rot_dif = ee->rotation - rotation; */
+/*    if (rot_dif < 0) rot_dif = -rot_dif; */
+/*    if (!strcmp(ee->driver, "software_ddraw")) */
+/*      { */
+/*     Evas_Engine_Info_Software_16_WinCE *einfo; */
+
+/*     einfo = (Evas_Engine_Info_Software_16_WinCE *)evas_engine_info_get(ee->evas); */
+/*     if (!einfo) return; */
+/*     if (rot_dif != 180) */
+/*       { */
+/*          int minw, minh, maxw, maxh, basew, baseh, stepw, steph; */
+
+/*          einfo->info.rotation = rotation; */
+/*          evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); */
+/*          if (!ee->prop.fullscreen) */
+/*            { */
+/*               ecore_wince_window_resize(ee->prop.window, ee->h, ee->w); */
+/*               ee->expecting_resize.w = ee->h; */
+/*               ee->expecting_resize.h = ee->w; */
+/*            } */
+/*          else */
+/*            { */
+/*               int w, h; */
+
+/*               ecore_wince_window_size_get(ee->prop.window, &w, &h); */
+/*               ecore_wince_window_resize(ee->prop.window, h, w); */
+/*               if ((rotation == 0) || (rotation == 180)) */
+/*                 { */
+/*                    evas_output_size_set(ee->evas, ee->w, ee->h); */
+/*                    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); */
+/*                 } */
+/*               else */
+/*                 { */
+/*                    evas_output_size_set(ee->evas, ee->h, ee->w); */
+/*                    evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); */
+/*                 } */
+/*               if (ee->func.fn_resize) ee->func.fn_resize(ee); */
+/*            } */
+/*          ecore_evas_size_min_get(ee, &minw, &minh); */
+/*          ecore_evas_size_max_get(ee, &maxw, &maxh); */
+/*          ecore_evas_size_base_get(ee, &basew, &baseh); */
+/*          ecore_evas_size_step_get(ee, &stepw, &steph); */
+/*          ee->rotation = rotation; */
+/*          ecore_evas_size_min_set(ee, minh, minw); */
+/*          ecore_evas_size_max_set(ee, maxh, maxw); */
+/*          ecore_evas_size_base_set(ee, baseh, basew); */
+/*          ecore_evas_size_step_set(ee, steph, stepw); */
+/*          _ecore_evas_wince_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, */
+/*                                                   ecore_wince_current_time_get()); */
+/*       } */
+/*     else */
+/*       { */
+/*          einfo->info.rotation = rotation; */
+/*          evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); */
+/*          ee->rotation = rotation; */
+/*          _ecore_evas_wince_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, */
+/*                                                   ecore_wince_current_time_get()); */
+/*          if (ee->func.fn_resize) ee->func.fn_resize(ee); */
+/*       } */
+/*     if ((ee->rotation == 90) || (ee->rotation == 270)) */
+/*       evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w); */
+/*     else */
+/*       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); */
+/*      } */
+/* } */
+
+static void
+_ecore_evas_wince_show(Ecore_Evas *ee)
+{
+   INF("ecore evas show");
+
+   ee->should_be_visible = 1;
+   if (ee->prop.avoid_damage)
+     _ecore_evas_wince_render(ee);
+   ecore_wince_window_show((Ecore_WinCE_Window *)ee->prop.window);
+/*    if (ee->prop.fullscreen) */
+/*      ecore_wince_window_focus(ee->prop.window); */
+}
+
+static void
+_ecore_evas_wince_hide(Ecore_Evas *ee)
+{
+   INF("ecore evas hide");
+
+   ecore_wince_window_hide((Ecore_WinCE_Window *)ee->prop.window);
+   ee->should_be_visible = 0;
+}
+
+/* static void */
+/* _ecore_evas_wince_raise(Ecore_Evas *ee) */
+/* { */
+/*    if (!ee->prop.fullscreen) */
+/*      ecore_wince_window_raise(ee->prop.window); */
+/*    else */
+/*      ecore_wince_window_raise(ee->prop.window); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_lower(Ecore_Evas *ee) */
+/* { */
+/*    if (!ee->prop.fullscreen) */
+/*      ecore_wince_window_lower(ee->prop.window); */
+/*    else */
+/*      ecore_wince_window_lower(ee->prop.window); */
+/* } */
+
+static void
+_ecore_evas_wince_title_set(Ecore_Evas *ee, const char *title)
+{
+   INF("ecore evas title set");
+
+   if (ee->prop.title) free(ee->prop.title);
+   ee->prop.title = NULL;
+   if (title) ee->prop.title = strdup(title);
+   ecore_wince_window_title_set((Ecore_WinCE_Window *)ee->prop.window, ee->prop.title);
+}
+
+/* static void */
+/* _ecore_evas_wince_size_min_set(Ecore_Evas *ee, int width, int height) */
+/* { */
+/*    if (width < 0) width = 0; */
+/*    if (height < 0) height = 0; */
+/*    if ((ee->prop.min.w == width) && (ee->prop.min.h == height)) return; */
+/*    ee->prop.min.w = width; */
+/*    ee->prop.min.h = height; */
+/*    ecore_wince_window_size_min_set(ee->prop.window, width, height); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_size_max_set(Ecore_Evas *ee, int width, int height) */
+/* { */
+/*    if (width < 0) width = 0; */
+/*    if (height < 0) height = 0; */
+/*    if ((ee->prop.max.w == width) && (ee->prop.max.h == height)) return; */
+/*    ee->prop.max.w = width; */
+/*    ee->prop.max.h = height; */
+/*    ecore_wince_window_size_max_set(ee->prop.window, width, height); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_size_base_set(Ecore_Evas *ee, int width, int height) */
+/* { */
+/*    if (width < 0) width = 0; */
+/*    if (height < 0) height = 0; */
+/*    if ((ee->prop.base.w == width) && (ee->prop.base.h == height)) return; */
+/*    ee->prop.base.w = width; */
+/*    ee->prop.base.h = height; */
+/*    ecore_wince_window_size_base_set(ee->prop.window, width, height); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_size_step_set(Ecore_Evas *ee, int width, int height) */
+/* { */
+/*    if (width < 1) width = 1; */
+/*    if (height < 1) height = 1; */
+/*    if ((ee->prop.step.w == width) && (ee->prop.step.h == height)) return; */
+/*    ee->prop.step.w = width; */
+/*    ee->prop.step.h = height; */
+/*    ecore_wince_window_size_step_set(ee->prop.window, width, height); */
+/* } */
+
+static void
+_ecore_evas_wince_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+#if 0
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+       ee->prop.cursor.object = NULL;
+       ee->prop.cursor.layer = 0;
+       ee->prop.cursor.hot.x = 0;
+       ee->prop.cursor.hot.y = 0;
+       ecore_wince_window_cursor_show(ee->prop.window, 1);
+       return;
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+
+   ecore_wince_window_cursor_show(ee->prop.window, 0);
+
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                   x - ee->prop.cursor.hot.x,
+                   y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+#endif
+}
+
+/* static void */
+/* _ecore_evas_wince_focus_set(Ecore_Evas *ee, int on __UNUSED__) */
+/* { */
+/*    ecore_wince_window_focus_set(ee->prop.window); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_iconified_set(Ecore_Evas *ee, int on) */
+/* { */
+/* /\*    if (((ee->prop.borderless) && (on)) || *\/ */
+/* /\*        ((!ee->prop.borderless) && (!on))) return; *\/ */
+/*    ee->prop.iconified = on; */
+/*    ecore_wince_window_iconified_set(ee->prop.window, ee->prop.iconified); */
+/* } */
+
+/* static void */
+/* _ecore_evas_wince_borderless_set(Ecore_Evas *ee, int on) */
+/* { */
+/*    if (((ee->prop.borderless) && (on)) || */
+/*        ((!ee->prop.borderless) && (!on))) return; */
+/*    ee->prop.borderless = on; */
+/*    ecore_wince_window_borderless_set(ee->prop.window, ee->prop.borderless); */
+/* } */
+
+static void
+_ecore_evas_wince_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   Evas_Engine_Info_Software_16_WinCE *einfo;
+   struct _Ecore_WinCE_Window         *window;
+
+   INF("ecore evas fullscreen set");
+
+   if ((ee->engine.wince.state.fullscreen && on) ||
+      (!ee->engine.wince.state.fullscreen && !on))
+     return;
+
+   ee->engine.wince.state.fullscreen = on;
+   ee->prop.fullscreen = on;
+
+   window = (struct _Ecore_WinCE_Window *)ee->prop.window;
+
+   if (on != 0)
+   {
+/*       ecore_win32_window_shape_set(ee->engine.win32.window, 0, 0, NULL); */
+      ecore_wince_window_fullscreen_set((Ecore_WinCE_Window *)ee->prop.window, on);
+      ee->w = GetSystemMetrics(SM_CXSCREEN);
+      ee->h = GetSystemMetrics(SM_CYSCREEN);
+      evas_output_size_set(ee->evas, ee->w, ee->h);
+      evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   }
+   else
+   {
+      int w;
+      int h;
+
+      ecore_wince_window_fullscreen_set((Ecore_WinCE_Window *)ee->prop.window, on);
+      ecore_wince_window_size_get((Ecore_WinCE_Window *)ee->prop.window, &w, &h);
+      ee->w = w;
+      ee->h = h;
+      evas_output_size_set(ee->evas, ee->w, ee->h);
+      evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+/*       ecore_win32_window_shape_set(window, */
+/*                                    window->shape.width, */
+/*                                    window->shape.height, */
+/*                                    window->shape.mask); */
+   }
+
+   einfo = (Evas_Engine_Info_Software_16_WinCE *)evas_engine_info_get(ecore_evas_get(ee));
+   if (einfo != NULL)
+     {
+        einfo->info.fullscreen = !!on;
+/*         einfo->info.layered = window->shape.layered; */
+        evas_engine_info_set(ecore_evas_get(ee), (Evas_Engine_Info *)einfo);
+     }
+}
+
+static Ecore_Evas_Engine_Func _ecore_wince_engine_func =
+{
+   _ecore_evas_wince_free,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_wince_callback_delete_request_set,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   _ecore_evas_wince_move,
+   NULL,
+   _ecore_evas_wince_resize,
+   _ecore_evas_wince_move_resize,
+   NULL, //_ecore_evas_wince_rotation_set,
+   NULL, /* _ecore_evas_x_shaped_set */
+   _ecore_evas_wince_show,
+   _ecore_evas_wince_hide,
+   NULL, //_ecore_evas_wince_raise,
+   NULL, //_ecore_evas_wince_lower,
+   NULL, //_ecore_evas_wince_activate,
+   _ecore_evas_wince_title_set,
+   NULL, /* _ecore_evas_x_name_class_set */
+   NULL, //_ecore_evas_wince_size_min_set,
+   NULL, //_ecore_evas_wince_size_max_set,
+   NULL, //_ecore_evas_wince_size_base_set,
+   NULL, //_ecore_evas_wince_size_step_set,
+   _ecore_evas_wince_cursor_set,
+   NULL, /* _ecore_evas_x_layer_set */
+   NULL, //_ecore_evas_wince_focus_set,
+   NULL, //_ecore_evas_wince_iconified_set,
+   NULL, //_ecore_evas_wince_borderless_set,
+   NULL, /* _ecore_evas_x_override_set */
+   NULL,
+   _ecore_evas_wince_fullscreen_set,
+   NULL, /* _ecore_evas_x_avoid_damage_set */
+   NULL, /* _ecore_evas_x_withdrawn_set */
+   NULL, /* _ecore_evas_x_sticky_set */
+   NULL, /* _ecore_evas_x_ignore_events_set */
+   NULL, /* _ecore_evas_x_alpha_set */
+   NULL, //transparent
+     
+     NULL // render
+};
+
+/* API */
+
+static Ecore_Evas *
+ecore_evas_software_wince_new_internal(int                 backend,
+                                       Ecore_WinCE_Window *parent,
+                                       int                 x,
+                                       int                 y,
+                                       int                 width,
+                                       int                 height,
+                                       int                 fullscreen)
+{
+   Evas_Engine_Info_Software_16_WinCE *einfo;
+   Ecore_Evas                         *ee;
+   int                                 rmethod;
+
+   rmethod = evas_render_method_lookup("software_16_wince");
+   if (!rmethod)
+     return NULL;
+
+   if (!ecore_wince_init())
+     return NULL;
+
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee)
+     {
+        ecore_wince_shutdown();
+        return NULL;
+     }
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   if (!_ecore_evas_wince_init())
+     {
+        free(ee);
+        ecore_wince_shutdown();
+        return NULL;
+     }
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wince_engine_func;
+
+   ee->driver = "software_16_wince";
+
+   if (width < 1) width = 1;
+   if (height < 1) height = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = width;
+   ee->h = height;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   /* FIXME: sticky to add */
+
+   ee->prop.window = (Ecore_Window)ecore_wince_window_new((Ecore_WinCE_Window *)parent, x, y, width, height);
+   if (!ee->prop.window)
+     {
+        _ecore_evas_wince_shutdown();
+        free(ee);
+        ecore_wince_shutdown();
+        return NULL;
+     }
+
+   ecore_wince_window_fullscreen_set((Ecore_WinCE_Window *)ee->prop.window, fullscreen);
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, width, height);
+   evas_output_viewport_set(ee->evas, 0, 0, width, height);
+
+   einfo = (Evas_Engine_Info_Software_16_WinCE *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        /* FIXME: REDRAW_DEBUG missing for now */
+        einfo->info.window = ((struct _Ecore_WinCE_Window *)ee->prop.window)->window;
+        einfo->info.width = width;
+        einfo->info.height = height;
+        einfo->info.backend = backend;
+        einfo->info.rotation = 0;
+        einfo->info.fullscreen = fullscreen;
+       evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+
+        ecore_wince_window_backend_set((Ecore_WinCE_Window *)ee->prop.window, backend);
+        ecore_wince_window_suspend_set((Ecore_WinCE_Window *)ee->prop.window, einfo->func.suspend);
+        ecore_wince_window_resume_set((Ecore_WinCE_Window *)ee->prop.window, einfo->func.resume);
+     }
+
+   ee->engine.func->fn_render = _ecore_evas_wince_render;
+   _ecore_evas_register(ee);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process);
+   evas_focus_in(ee->evas);
+
+   return ee;
+}
+
+#else
+
+static Ecore_Evas *
+ecore_evas_software_wince_new_internal(int                 backend __UNUSED__,
+                                       Ecore_WinCE_Window *parent __UNUSED__,
+                                       int                 x __UNUSED__,
+                                       int                 y __UNUSED__,
+                                       int                 width __UNUSED__,
+                                       int                 height __UNUSED__,
+                                       int                 fullscreen __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_WINCE */
+
+
+EAPI Ecore_Evas *
+ecore_evas_software_wince_new(Ecore_WinCE_Window *parent,
+                              int                 x,
+                              int                 y,
+                              int                 width,
+                              int                 height)
+{
+   return ecore_evas_software_wince_new_internal(0, parent, x, y, width, height, 1);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_software_wince_fb_new(Ecore_WinCE_Window *parent,
+                                 int                 x,
+                                 int                 y,
+                                 int                 width,
+                                 int                 height)
+{
+   return ecore_evas_software_wince_new_internal(1, parent, x, y, width, height, 1);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_software_wince_gapi_new(Ecore_WinCE_Window *parent,
+                                   int                 x,
+                                   int                 y,
+                                   int                 width,
+                                   int                 height)
+{
+   return ecore_evas_software_wince_new_internal(2, parent, x, y, width, height, 1);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_software_wince_ddraw_new(Ecore_WinCE_Window *parent,
+                                    int                 x,
+                                    int                 y,
+                                    int                 width,
+                                    int                 height)
+{
+   return ecore_evas_software_wince_new_internal(3, parent, x, y, width, height, 1);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_software_wince_gdi_new(Ecore_WinCE_Window *parent,
+                                  int                 x,
+                                  int                 y,
+                                  int                 width,
+                                  int                 height)
+{
+   return ecore_evas_software_wince_new_internal(4, parent, x, y, width, height, 0);
+}
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
+
+EAPI Ecore_WinCE_Window *
+ecore_evas_software_wince_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_WinCE_Window *) ecore_evas_window_get(ee);
+}
+
+#else
+
+EAPI Ecore_WinCE_Window *
+ecore_evas_software_wince_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return NULL;
+}
+
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_WINCE */
diff --git a/src/lib/ecore_evas/ecore_evas_x.c b/src/lib/ecore_evas/ecore_evas_x.c
new file mode 100644 (file)
index 0000000..ff5a36e
--- /dev/null
@@ -0,0 +1,3764 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <Ecore.h>
+#include <Ecore_Input.h>
+#include <Ecore_Input_Evas.h>
+#ifdef BUILD_ECORE_EVAS_X11
+# include <Ecore_X.h>
+# include <Ecore_X_Atoms.h>
+#endif
+
+#include "ecore_evas_private.h"
+#include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_X11
+static int _ecore_evas_init_count = 0;
+
+static Ecore_Event_Handler *ecore_evas_event_handlers[13];
+
+static void
+_ecore_evas_x_protocols_set(Ecore_Evas *ee)
+{
+   Ecore_X_Atom protos[10];
+   int num = 0;
+   
+   if (ee->func.fn_delete_request)
+     protos[num++] = ECORE_X_ATOM_WM_DELETE_WINDOW;
+   protos[num++] = ECORE_X_ATOM_NET_WM_PING;
+   ecore_x_icccm_protocol_atoms_set(ee->prop.window, protos, num);
+}
+
+static void
+_ecore_evas_x_sync_set(Ecore_Evas *ee)
+{
+   if ((ecore_x_e_comp_sync_supported_get(ee->engine.x.win_root)) &&
+       (!ee->no_comp_sync) && (_ecore_evas_app_comp_sync))
+     {
+        if (!ee->engine.x.sync_counter)
+          ee->engine.x.sync_counter = ecore_x_sync_counter_new(0);
+     }
+   else
+     {
+        if (ee->engine.x.sync_counter)
+          ecore_x_sync_counter_free(ee->engine.x.sync_counter);
+        ee->engine.x.sync_counter = 0;
+     }
+   ecore_x_e_comp_sync_counter_set(ee->prop.window, ee->engine.x.sync_counter);
+}
+
+static void
+_ecore_evas_x_sync_clear(Ecore_Evas *ee)
+{
+   if (!ee->engine.x.sync_counter) return;
+   ecore_x_sync_counter_free(ee->engine.x.sync_counter);
+   ee->engine.x.sync_counter = 0;
+}
+
+#ifdef HAVE_ECORE_X_XCB
+static xcb_visualtype_t *
+xcb_visualtype_get(xcb_screen_t *screen, xcb_visualid_t visual)
+{
+   xcb_depth_iterator_t  iter_depth;
+
+   if (!screen) return NULL;
+
+   iter_depth = xcb_screen_allowed_depths_iterator(screen);
+   for (; iter_depth.rem; xcb_depth_next (&iter_depth))
+     {
+        xcb_visualtype_iterator_t iter_vis;
+
+        iter_vis = xcb_depth_visuals_iterator(iter_depth.data);
+        for (; iter_vis.rem; --screen, xcb_visualtype_next (&iter_vis))
+          {
+            if (visual == iter_vis.data->visual_id)
+              return iter_vis.data;
+          }
+     }
+
+   return NULL;
+}
+#endif /* HAVE_ECORE_X_XCB */
+
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+# ifdef HAVE_ECORE_X_XCB
+/* noop */
+# else
+static Ecore_X_Window
+_ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, int w, int h, int override, int argb, const int *opt)
+{
+   Evas_Engine_Info_GL_X11 *einfo;
+   Ecore_X_Window win;
+
+   einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+       XSetWindowAttributes attr;
+       int screen;
+
+        if (opt)
+          {
+             int op;
+             
+             for (op = 0; opt[op]; op++)
+               {
+                  if (opt[op] == ECORE_EVAS_GL_X11_OPT_INDIRECT)
+                    {
+                       op++;
+                       einfo->indirect = opt[op];
+                    }
+               }
+          }
+        
+       /* FIXME: this is inefficient as its 1 or more round trips */
+       screen = DefaultScreen(ecore_x_display_get());
+       if (ScreenCount(ecore_x_display_get()) > 1)
+         {
+            Ecore_X_Window *roots;
+            int num, i;
+
+            num = 0;
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                 XWindowAttributes at;
+
+                 if (XGetWindowAttributes(ecore_x_display_get(),
+                                          parent, &at))
+                   {
+                      for (i = 0; i < num; i++)
+                        {
+                           if (at.root == roots[i])
+                             {
+                                screen = i;
+                                break;
+                             }
+                        }
+                   }
+                 free(roots);
+              }
+         }
+       einfo->info.display  = ecore_x_display_get();
+        einfo->info.screen   = screen;
+        
+        einfo->info.destination_alpha = argb;
+        
+       einfo->info.visual   = einfo->func.best_visual_get(einfo);
+       einfo->info.colormap = einfo->func.best_colormap_get(einfo);
+       einfo->info.depth    = einfo->func.best_depth_get(einfo);
+        
+
+        if ((!einfo->info.visual) ||
+            (!einfo->info.colormap) ||
+            (!einfo->info.depth))
+          {
+             WRN("OpenGL X11 init engine '%s' failed - no visual, colormap or depth.", ee->driver);
+             evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+             return 0;
+          }
+        
+       attr.backing_store = NotUseful;
+       attr.override_redirect = override;
+       attr.colormap = einfo->info.colormap;
+       attr.border_pixel = 0;
+       attr.background_pixmap = None;
+       attr.event_mask =
+         KeyPressMask | KeyReleaseMask |
+         ExposureMask | ButtonPressMask | ButtonReleaseMask |
+         EnterWindowMask | LeaveWindowMask |
+         PointerMotionMask | StructureNotifyMask | VisibilityChangeMask |
+         FocusChangeMask | PropertyChangeMask | ColormapChangeMask;
+       attr.bit_gravity = ForgetGravity;
+
+       win =
+         XCreateWindow(einfo->info.display, parent, x, y, w, h, 0,
+                       einfo->info.depth, InputOutput, einfo->info.visual,
+                       CWBackingStore | CWColormap | CWBackPixmap | 
+                        CWBorderPixel | CWBitGravity | CWEventMask |
+                       CWOverrideRedirect, &attr);
+       einfo->info.drawable = win;
+        
+       if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             WRN("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+             XDestroyWindow(einfo->info.display, win);
+             return 0;
+          }
+        ecore_x_window_defaults_set(win);
+        _ecore_evas_x_protocols_set(ee);
+        _ecore_evas_x_sync_set(ee);
+    }
+   else
+     {
+       win = 0;
+     }
+   return win;
+}
+#endif /* HAVE_ECORE_X_XCB */
+#endif
+
+static int
+_ecore_evas_x_render(Ecore_Evas *ee)
+{
+   Eina_Rectangle *r;
+   Eina_List *updates, *l;
+   int rend = 0;
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
+   Eina_List *ll;
+   Ecore_Evas *ee2;
+
+   if ((!ee->no_comp_sync) && (_ecore_evas_app_comp_sync) &&
+       (ee->engine.x.sync_counter) && (!ee->engine.x.sync_began) &&
+       (!ee->engine.x.sync_cancel))
+     return 0;
+   
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+       if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+       rend |= _ecore_evas_buffer_render(ee2);
+       if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+#endif
+   if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+   if (ee->prop.avoid_damage)
+     {
+       updates = evas_render_updates(ee->evas);
+       if (ee->engine.x.using_bg_pixmap)
+         {
+            if (updates)
+              {
+                 EINA_LIST_FOREACH(updates, l, r)
+                   ecore_x_window_area_clear(ee->prop.window, r->x, r->y, r->w, r->h);
+                 if ((ee->shaped) && (updates))
+                   ecore_x_window_shape_mask_set(ee->prop.window, ee->engine.x.mask);
+//               if ((ee->alpha) && (updates))
+//                 ecore_x_window_shape_input_mask_set(ee->prop.window, ee->engine.x.mask);
+                 evas_render_updates_free(updates);
+                 _ecore_evas_idle_timeout_update(ee);
+                  rend = 1;
+              }
+         }
+       else
+         {
+            EINA_LIST_FOREACH(updates, l, r)
+              {
+                 Ecore_X_Rectangle rect;
+                 Ecore_X_XRegion  *tmpr;
+
+                 if (!ee->engine.x.damages)
+                   ee->engine.x.damages = ecore_x_xregion_new();
+                 tmpr = ecore_x_xregion_new();
+                 if (ee->rotation == 0)
+                   {
+                      rect.x = r->x;
+                      rect.y = r->y;
+                      rect.width = r->w;
+                      rect.height = r->h;
+                   }
+                 else if (ee->rotation == 90)
+                   {
+                      rect.x = r->y;
+                      rect.y = ee->h - r->x - r->w;
+                      rect.width = r->h;
+                      rect.height = r->w;
+                   }
+                 else if (ee->rotation == 180)
+                   {
+                      rect.x = ee->w - r->x - r->w;
+                      rect.y = ee->h - r->y - r->h;
+                      rect.width = r->w;
+                      rect.height = r->h;
+                   }
+                 else if (ee->rotation == 270)
+                   {
+                      rect.x = ee->w - r->y - r->h;
+                      rect.y = r->x;
+                      rect.width = r->h;
+                      rect.height = r->w;
+                   }
+                  ecore_x_xregion_union_rect(tmpr, ee->engine.x.damages, &rect);
+                 ecore_x_xregion_free(ee->engine.x.damages);
+                 ee->engine.x.damages = tmpr;
+              }
+            if (ee->engine.x.damages)
+              {
+                 /* if we have a damage pixmap - we can avoid exposures by
+                  * disabling them just for setting the mask */
+                 ecore_x_event_mask_set(ee->prop.window,
+                                        ECORE_X_EVENT_MASK_KEY_DOWN |
+                                        ECORE_X_EVENT_MASK_KEY_UP |
+                                        ECORE_X_EVENT_MASK_MOUSE_DOWN |
+                                        ECORE_X_EVENT_MASK_MOUSE_UP |
+                                        ECORE_X_EVENT_MASK_MOUSE_IN |
+                                        ECORE_X_EVENT_MASK_MOUSE_OUT |
+                                        ECORE_X_EVENT_MASK_MOUSE_MOVE |
+//                                      ECORE_X_EVENT_MASK_WINDOW_DAMAGE |
+                                        ECORE_X_EVENT_MASK_WINDOW_VISIBILITY |
+                                        ECORE_X_EVENT_MASK_WINDOW_CONFIGURE |
+                                        ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE |
+                                        ECORE_X_EVENT_MASK_WINDOW_PROPERTY |
+                                        ECORE_X_EVENT_MASK_WINDOW_COLORMAP
+                                        );
+                 if ((ee->shaped) && (updates))
+                   ecore_x_window_shape_mask_set(ee->prop.window, ee->engine.x.mask);
+                 /* and re-enable them again */
+                 ecore_x_event_mask_set(ee->prop.window,
+                                        ECORE_X_EVENT_MASK_KEY_DOWN |
+                                        ECORE_X_EVENT_MASK_KEY_UP |
+                                        ECORE_X_EVENT_MASK_MOUSE_DOWN |
+                                        ECORE_X_EVENT_MASK_MOUSE_UP |
+                                        ECORE_X_EVENT_MASK_MOUSE_IN |
+                                        ECORE_X_EVENT_MASK_MOUSE_OUT |
+                                        ECORE_X_EVENT_MASK_MOUSE_MOVE |
+                                        ECORE_X_EVENT_MASK_WINDOW_DAMAGE |
+                                        ECORE_X_EVENT_MASK_WINDOW_VISIBILITY |
+                                        ECORE_X_EVENT_MASK_WINDOW_CONFIGURE |
+                                        ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE |
+                                        ECORE_X_EVENT_MASK_WINDOW_PROPERTY |
+                                        ECORE_X_EVENT_MASK_WINDOW_COLORMAP
+                                        );
+                 ecore_x_xregion_set(ee->engine.x.damages, ee->engine.x.gc);
+                 /* debug rendering */
+                 /*
+                  XSetForeground(ecore_x_display_get(), ee->engine.x.gc, rand());
+                  XFillRectangle(ecore_x_display_get(), ee->prop.window, ee->engine.x.gc,
+                  0, 0, ee->w, ee->h);
+                  XSync(ecore_x_display_get(), False);
+                  usleep(20000);
+                  XSync(ecore_x_display_get(), False);
+                  */
+                 ecore_x_pixmap_paste(ee->engine.x.pmap, ee->prop.window, ee->engine.x.gc,
+                                      0, 0, ee->w, ee->h, 0, 0);
+                 ecore_x_xregion_free(ee->engine.x.damages);
+                 ee->engine.x.damages = NULL;
+              }
+            if (updates)
+              {
+                 evas_render_updates_free(updates);
+                 _ecore_evas_idle_timeout_update(ee);
+                  rend = 1;
+              }
+         }
+     }
+   else if (((ee->visible) && (ee->draw_ok)) ||
+           ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
+           ((ee->should_be_visible) && (ee->prop.override)))
+     {
+
+        updates = evas_render_updates(ee->evas);
+        if (updates) 
+          {
+             if (ee->shaped) 
+               ecore_x_window_shape_mask_set(ee->prop.window, ee->engine.x.mask);
+//             if (ee->alpha)
+//               ecore_x_window_shape_input_mask_set(ee->prop.window, ee->engine.x.mask);
+             evas_render_updates_free(updates);
+             _ecore_evas_idle_timeout_update(ee);
+             rend = 1;
+          }
+     }
+   else
+     evas_norender(ee->evas);
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+/*   
+   if (rend)
+     {
+        static int frames = 0;
+        static double t0 = 0.0;
+        double t, td;
+        
+        t = ecore_time_get();
+        frames++;
+        if ((t - t0) > 1.0)
+          {
+             td = t - t0;
+             printf("FPS: %3.3f\n", (double)frames / td);
+             frames = 0;
+             t0 = t;
+          }
+     }
+ */
+   return rend;
+}
+
+static void
+_ecore_evas_x_resize_shape(Ecore_Evas *ee)
+{
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+             unsigned int    foreground;
+            Ecore_X_GC      gc;
+
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+             foreground = 0;
+             gc = ecore_x_gc_new(ee->engine.x.mask,
+                                 ECORE_X_GC_VALUE_MASK_FOREGROUND,
+                                 &foreground);
+             ecore_x_drawable_rectangle_fill(ee->engine.x.mask, gc,
+                                             0, 0, ee->w, ee->h);
+             ecore_x_gc_free(gc);
+            einfo->info.mask = ee->engine.x.mask;
+             if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+               {
+                  ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+               }
+            evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+         }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
+     }
+   else if (!strcmp(ee->driver, "xrender_x11"))
+     {
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+       Evas_Engine_Info_XRender_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+             unsigned int    foreground;
+            Ecore_X_GC      gc;
+
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+             foreground = 0;
+             gc = ecore_x_gc_new(ee->engine.x.mask,
+                                ECORE_X_GC_VALUE_MASK_FOREGROUND,
+                                &foreground);
+             ecore_x_drawable_rectangle_fill(ee->engine.x.mask, gc,
+                                             0, 0, ee->w, ee->h);
+             ecore_x_gc_free(gc);
+            einfo->info.mask = ee->engine.x.mask;
+             if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+               {
+                  ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+               }
+            evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+         }
+#endif /* BUILD_ECORE_EVAS_XRENDER_X11 || BUILD_ECORE_EVAS_XRENDER_XCB */
+     }
+   else if (!strcmp(ee->driver, "software_16_x11"))
+     {
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+# if 0 /* XXX no shaped window support for software_16_x11 */
+       Evas_Engine_Info_Software_16_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+            einfo->info.mask = ee->engine.x.mask;
+             if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+               {
+                  ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+               }
+            evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+         }
+# endif /* XXX no shaped window support for software_16_x11 */
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+     }
+}
+
+/* TODO: we need to make this work for all the states, not just sticky */
+static int
+_ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Property *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
+     {
+       unsigned int i, num;
+       Ecore_X_Window_State *state;
+       int sticky;
+
+#ifdef HAVE_ECORE_X_XCB
+        ecore_x_netwm_window_state_get_prefetch(e->win);
+#endif /* HAVE_ECORE_X_XCB */
+       sticky = 0;
+
+       /* TODO: we need to move those to the end, with if statements */
+       ee->engine.x.state.modal = 0;
+       ee->engine.x.state.maximized_v = 0;
+       ee->engine.x.state.maximized_h = 0;
+       ee->engine.x.state.shaded = 0;
+       ee->engine.x.state.skip_taskbar = 0;
+       ee->engine.x.state.skip_pager = 0;
+       ee->prop.fullscreen = 0;
+       ee->engine.x.state.fullscreen = 0;
+       ee->engine.x.state.above = 0;
+       ee->engine.x.state.below = 0;
+
+#ifdef HAVE_ECORE_X_XCB
+        ecore_x_netwm_window_state_get_fetch();
+#endif /* HAVE_ECORE_X_XCB */
+       ecore_x_netwm_window_state_get(e->win, &state, &num);
+       if (state)
+         {
+            for (i = 0; i < num; i++)
+              {
+                 switch (state[i])
+                   {
+                    case ECORE_X_WINDOW_STATE_MODAL:
+                       ee->engine.x.state.modal = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_STICKY:
+                       if (ee->prop.sticky && ee->engine.x.state.sticky)
+                         break;
+
+                       sticky = 1;
+                       ee->prop.sticky = 1;
+                       ee->engine.x.state.sticky = 1;
+                       if (ee->func.fn_sticky) ee->func.fn_sticky(ee);
+                       break;
+                    case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
+                       ee->engine.x.state.maximized_v = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
+                       ee->engine.x.state.maximized_h = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_SHADED:
+                       ee->engine.x.state.shaded = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
+                       ee->engine.x.state.skip_taskbar = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_SKIP_PAGER:
+                       ee->engine.x.state.skip_pager = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_FULLSCREEN:
+                       ee->prop.fullscreen = 1;
+                       ee->engine.x.state.fullscreen = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_ABOVE:
+                       ee->engine.x.state.above = 1;
+                       break;
+                    case ECORE_X_WINDOW_STATE_BELOW:
+                       ee->engine.x.state.below = 1;
+                       break;
+                    default:
+                       break;
+                   }
+              }
+            free(state);
+         }
+#ifdef HAVE_ECORE_X_XCB
+        ecore_xcb_reply_free();
+#endif /* HAVE_ECORE_X_XCB */
+
+       if (ee->prop.sticky && !sticky)
+         {
+            ee->prop.sticky = 0;
+            ee->engine.x.state.sticky = 0;
+            if (ee->func.fn_unsticky) ee->func.fn_unsticky(ee);
+         }
+     }
+
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_visibility_change(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Visibility_Change *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+//   printf("VIS CHANGE OBSCURED: %p %i\n", ee, e->fully_obscured);
+   if (e->fully_obscured)
+     {
+        /* FIXME: round trip */
+        if (!ecore_x_screen_is_composited(ee->engine.x.screen_num))
+          ee->draw_ok = 0;
+     }
+   else ee->draw_ok = 1;
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_client_message(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Client_Message *e;
+
+   e = event;
+   if (e->format != 32) return 1;
+   if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_BEGIN)
+     {
+        ee = ecore_event_window_match(e->data.l[0]);
+        if (!ee) return 1; /* pass on event */
+        if (e->data.l[0] != (long)ee->prop.window) return 1;
+        ee->engine.x.sync_began = 1;
+        ee->engine.x.sync_cancel = 0;
+     }
+   else if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_END)
+     {
+        ee = ecore_event_window_match(e->data.l[0]);
+        if (!ee) return 1; /* pass on event */
+        if (e->data.l[0] != (long)ee->prop.window) return 1;
+        ee->engine.x.sync_began = 0;
+        ee->engine.x.sync_cancel = 0;
+     }
+   else if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_CANCEL)
+     {
+        ee = ecore_event_window_match(e->data.l[0]);
+        if (!ee) return 1; /* pass on event */
+        if (e->data.l[0] != (long)ee->prop.window) return 1;
+        ee->engine.x.sync_began = 0;
+        ee->engine.x.sync_cancel = 1;
+     }
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Mouse_In *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+/*    { */
+/*       time_t t; */
+/*       char *ct; */
+
+/*       const char *modes[] = { */
+/*     "MODE_NORMAL", */
+/*     "MODE_WHILE_GRABBED", */
+/*     "MODE_GRAB", */
+/*     "MODE_UNGRAB" */
+/*       }; */
+/*       const char *details[] = { */
+/*     "DETAIL_ANCESTOR", */
+/*     "DETAIL_VIRTUAL", */
+/*     "DETAIL_INFERIOR", */
+/*     "DETAIL_NON_LINEAR", */
+/*     "DETAIL_NON_LINEAR_VIRTUAL", */
+/*     "DETAIL_POINTER", */
+/*     "DETAIL_POINTER_ROOT", */
+/*     "DETAIL_DETAIL_NONE" */
+/*       }; */
+/*       t = time(NULL); */
+/*       ct = ctime(&t); */
+/*       ct[strlen(ct) - 1] = 0; */
+/*       printf("@@ ->IN 0x%x 0x%x %s md=%s dt=%s\n", */
+/*          e->win, e->event_win, */
+/*          ct, */
+/*          modes[e->mode], */
+/*          details[e->detail]); */
+/*    } */
+   // disable. causes mroe problems than it fixes
+   //   if ((e->mode == ECORE_X_EVENT_MODE_GRAB) ||
+   //       (e->mode == ECORE_X_EVENT_MODE_UNGRAB))
+   //     return 0;
+   /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */
+   if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
+   ecore_event_evas_modifier_lock_update(ee->evas, e->modifiers);
+   evas_event_feed_mouse_in(ee->evas, e->time, NULL);
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Mouse_Out *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if ((!ee) || (ee->ignore_events)) return 1;
+   /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+/*    { */
+/*       time_t t; */
+/*       char *ct; */
+
+/*       const char *modes[] = { */
+/*     "MODE_NORMAL", */
+/*     "MODE_WHILE_GRABBED", */
+/*     "MODE_GRAB", */
+/*     "MODE_UNGRAB" */
+/*       }; */
+/*       const char *details[] = { */
+/*     "DETAIL_ANCESTOR", */
+/*     "DETAIL_VIRTUAL", */
+/*     "DETAIL_INFERIOR", */
+/*     "DETAIL_NON_LINEAR", */
+/*     "DETAIL_NON_LINEAR_VIRTUAL", */
+/*     "DETAIL_POINTER", */
+/*     "DETAIL_POINTER_ROOT", */
+/*     "DETAIL_DETAIL_NONE" */
+/*       }; */
+/*       t = time(NULL); */
+/*       ct = ctime(&t); */
+/*       ct[strlen(ct) - 1] = 0; */
+/*       printf("@@ ->OUT 0x%x 0x%x %s md=%s dt=%s\n", */
+/*          e->win, e->event_win, */
+/*          ct, */
+/*          modes[e->mode], */
+/*          details[e->detail]); */
+/*    } */
+   // disable. causes more problems than it fixes
+   //   if ((e->mode == ECORE_X_EVENT_MODE_GRAB) ||
+   //       (e->mode == ECORE_X_EVENT_MODE_UNGRAB))
+   //     return 0;
+   /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */
+   ecore_event_evas_modifier_lock_update(ee->evas, e->modifiers);
+   _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
+   if (e->mode == ECORE_X_EVENT_MODE_GRAB)
+     evas_event_feed_mouse_cancel(ee->evas, e->time, NULL);
+   evas_event_feed_mouse_out(ee->evas, e->time, NULL);
+   if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
+   if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Focus_In *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return 1;
+   ee->prop.focused = 1;
+   evas_focus_in(ee->evas);
+   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Focus_Out *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (e->mode == ECORE_X_EVENT_MODE_GRAB) return 1;
+//   if (ee->prop.fullscreen)
+//     ecore_x_window_focus(ee->prop.window);
+   evas_focus_out(ee->evas);
+   ee->prop.focused = 0;
+   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Damage *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (ee->engine.x.using_bg_pixmap) return 1;
+//   printf("EXPOSE %p [%i] %i %i %ix%i\n", ee, ee->prop.avoid_damage, e->x, e->y, e->w, e->h);
+   if (ee->prop.avoid_damage)
+     {
+       Ecore_X_Rectangle rect;
+       Ecore_X_XRegion  *tmpr;
+
+       if (!ee->engine.x.damages) ee->engine.x.damages = ecore_x_xregion_new();
+       tmpr = ecore_x_xregion_new();
+       rect.x = e->x;
+       rect.y = e->y;
+       rect.width = e->w;
+       rect.height = e->h;
+       ecore_x_xregion_union_rect(tmpr, ee->engine.x.damages, &rect);
+       ecore_x_xregion_free(ee->engine.x.damages);
+       ee->engine.x.damages = tmpr;
+/* no - this breaks things badly. disable. Ecore_X_Rectangle != XRectangle - see
+ *  the typedefs in x's headers and ecore_x's. also same with Region - it's a pointer in x - not an X ID
+       Ecore_X_Rectangle rect;
+       Ecore_X_XRegion  *tmpr;
+
+       if (!ee->engine.x.damages) ee->engine.x.damages = ecore_x_xregion_new();
+       tmpr = ecore_x_xregion_new();
+       rect.x = e->x;
+       rect.y = e->y;
+       rect.width = e->w;
+       rect.height = e->h;
+       ecore_x_xregion_union_rect(tmpr, ee->engine.x.damages, &rect);
+       ecore_x_xregion_free(ee->engine.x.damages);
+       ee->engine.x.damages = tmpr;
+ */
+     }
+   else
+     {
+       if (ee->rotation == 0)
+         evas_damage_rectangle_add(ee->evas,
+                                   e->x,
+                                   e->y,
+                                   e->w, e->h);
+       else if (ee->rotation == 90)
+         evas_damage_rectangle_add(ee->evas,
+                                   ee->h - e->y - e->h,
+                                   e->x,
+                                   e->h, e->w);
+       else if (ee->rotation == 180)
+         evas_damage_rectangle_add(ee->evas,
+                                   ee->w - e->x - e->w,
+                                   ee->h - e->y - e->h,
+                                   e->w, e->h);
+       else if (ee->rotation == 270)
+         evas_damage_rectangle_add(ee->evas,
+                                   e->y,
+                                   ee->w - e->x - e->w,
+                                   e->h, e->w);
+     }
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Destroy *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (ee->func.fn_destroy) ee->func.fn_destroy(ee);
+   _ecore_evas_x_sync_clear(ee);
+   ecore_evas_free(ee);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Configure *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (ee->engine.x.direct_resize) return 1;
+
+   if ((e->from_wm) || (ee->prop.override))
+     {
+       if ((ee->x != e->x) || (ee->y != e->y))
+         {
+            ee->x = e->x;
+            ee->y = e->y;
+             ee->req.x = ee->x;
+             ee->req.y = ee->y;
+            if (ee->func.fn_move) ee->func.fn_move(ee);
+         }
+     }
+   if ((ee->w != e->w) || (ee->h != e->h))
+     {
+       ee->w = e->w;
+       ee->h = e->h;
+        ee->req.w = ee->w;
+        ee->req.h = ee->h;
+       if ((ee->rotation == 90) || (ee->rotation == 270))
+         {
+            evas_output_size_set(ee->evas, ee->h, ee->w);
+            evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+         }
+       else
+         {
+            evas_output_size_set(ee->evas, ee->w, ee->h);
+            evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+         }
+       if (ee->prop.avoid_damage)
+         {
+            int pdam;
+
+            pdam = ecore_evas_avoid_damage_get(ee);
+            ecore_evas_avoid_damage_set(ee, 0);
+            ecore_evas_avoid_damage_set(ee, pdam);
+         }
+       if ((ee->shaped) || (ee->alpha))
+         _ecore_evas_x_resize_shape(ee);
+       if ((ee->expecting_resize.w > 0) &&
+           (ee->expecting_resize.h > 0))
+         {
+            if ((ee->expecting_resize.w == ee->w) &&
+                (ee->expecting_resize.h == ee->h))
+              _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                             ecore_x_current_time_get());
+            ee->expecting_resize.w = 0;
+            ee->expecting_resize.h = 0;
+         }
+       if (ee->func.fn_resize) ee->func.fn_resize(ee);
+     }
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Delete_Request *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (ee->func.fn_delete_request) ee->func.fn_delete_request(ee);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Show *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (ee->visible) return 0; /* dont pass it on */
+//   printf("SHOW EVENT %p\n", ee);
+   ee->visible = 1;
+   if (ee->func.fn_show) ee->func.fn_show(ee);
+   return 1;
+}
+
+static int
+_ecore_evas_x_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_X_Event_Window_Hide *e;
+
+   e = event;
+   ee = ecore_event_window_match(e->win);
+   if (!ee) return 1; /* pass on event */
+   if (e->win != ee->prop.window) return 1;
+   if (!ee->visible) return 0; /* dont pass it on */
+//   printf("HIDE EVENT %p\n", ee);
+   ee->visible = 0;
+   if (ee->func.fn_hide) ee->func.fn_hide(ee);
+   return 1;
+}
+
+/* FIXME, should be in idler */
+/* FIXME, round trip */
+static void
+_ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee)
+{
+# ifdef HAVE_ECORE_X_XCB
+   ecore_x_icccm_size_pos_hints_get_prefetch(ee->prop.window);
+   ecore_x_icccm_size_pos_hints_get_fetch();
+# endif /* HAVE_ECORE_X_XCB */
+   ecore_x_icccm_size_pos_hints_set(ee->prop.window,
+                                   ee->prop.request_pos /*request_pos */,
+                                   ECORE_X_GRAVITY_NW /* gravity */,
+                                   ee->prop.min.w /* min_w */,
+                                   ee->prop.min.h /* min_h */,
+                                   ee->prop.max.w /* max_w */,
+                                   ee->prop.max.h /* max_h */,
+                                   ee->prop.base.w /* base_w */,
+                                   ee->prop.base.h /* base_h */,
+                                   ee->prop.step.w /* step_x */,
+                                   ee->prop.step.h /* step_y */,
+                                   0 /* min_aspect */,
+                                   0 /* max_aspect */);
+# ifdef HAVE_ECORE_X_XCB
+   ecore_xcb_reply_free();
+# endif /* HAVE_ECORE_X_XCB */
+}
+
+/* FIXME, should be in idler */
+static void
+_ecore_evas_x_state_update(Ecore_Evas *ee)
+{
+   Ecore_X_Window_State state[10];
+   int num;
+
+   num = 0;
+
+   /*
+   if (bd->client.netwm.state.modal)
+     state[num++] = ECORE_X_WINDOW_STATE_MODAL;
+   */
+   if (ee->engine.x.state.sticky)
+     state[num++] = ECORE_X_WINDOW_STATE_STICKY;
+   /*
+   if (bd->client.netwm.state.maximized_v)
+     state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
+   if (bd->client.netwm.state.maximized_h)
+     state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
+   if (bd->client.netwm.state.shaded)
+     state[num++] = ECORE_X_WINDOW_STATE_SHADED;
+   if (bd->client.netwm.state.skip_taskbar)
+     state[num++] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
+   if (bd->client.netwm.state.skip_pager)
+     state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
+   if (bd->client.netwm.state.hidden)
+     state[num++] = ECORE_X_WINDOW_STATE_HIDDEN;
+   */
+   if (ee->engine.x.state.fullscreen)
+     state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN;
+   if (ee->engine.x.state.above)
+     state[num++] = ECORE_X_WINDOW_STATE_ABOVE;
+   if (ee->engine.x.state.below)
+     state[num++] = ECORE_X_WINDOW_STATE_BELOW;
+
+   ecore_x_netwm_window_state_set(ee->prop.window, state, num);
+}
+
+static void
+_ecore_evas_x_layer_update(Ecore_Evas *ee)
+{
+   if (ee->should_be_visible)
+     {
+       /* We need to send a netwm request to the wm */
+       /* FIXME: Do we have to remove old state before adding new? */
+       if (ee->prop.layer < 3)
+         {
+            if (ee->engine.x.state.above)
+              {
+                 ee->engine.x.state.above = 0;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_ABOVE, -1, 0);
+              }
+            if (!ee->engine.x.state.below)
+              {
+                 ee->engine.x.state.below = 1;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_BELOW, -1, 1);
+              }
+         }
+       else if (ee->prop.layer > 5)
+         {
+            if (ee->engine.x.state.below)
+              {
+                 ee->engine.x.state.below = 0;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_BELOW, -1, 0);
+              }
+            if (!ee->engine.x.state.above)
+              {
+                 ee->engine.x.state.above = 1;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_ABOVE, -1, 1);
+              }
+         }
+       else
+         {
+            if (ee->engine.x.state.below)
+              {
+                 ee->engine.x.state.below = 0;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_BELOW, -1, 0);
+              }
+            if (ee->engine.x.state.above)
+              {
+                 ee->engine.x.state.above = 0;
+                 ecore_x_netwm_state_request_send(ee->prop.window,
+                                                  ee->engine.x.win_root,
+                                                  ECORE_X_WINDOW_STATE_ABOVE, -1, 0);
+              }
+         }
+     }
+   else
+     {
+       /* Just set the state */
+       if (ee->prop.layer < 3)
+         {
+            if ((ee->engine.x.state.above) || (!ee->engine.x.state.below))
+              {
+                 ee->engine.x.state.above = 0;
+                 ee->engine.x.state.below = 1;
+                 _ecore_evas_x_state_update(ee);
+              }
+         }
+       else if (ee->prop.layer > 5)
+         {
+            if ((!ee->engine.x.state.above) || (ee->engine.x.state.below))
+              {
+                 ee->engine.x.state.above = 1;
+                 ee->engine.x.state.below = 0;
+                 _ecore_evas_x_state_update(ee);
+              }
+         }
+       else
+         {
+            if ((ee->engine.x.state.above) || (ee->engine.x.state.below))
+              {
+                 ee->engine.x.state.above = 0;
+                 ee->engine.x.state.below = 0;
+                 _ecore_evas_x_state_update(ee);
+              }
+         }
+     }
+   /* FIXME: Set gnome layer */
+}
+
+static int
+_ecore_evas_x_init(void)
+{
+   _ecore_evas_init_count++;
+   if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+   ecore_evas_event_handlers[0]  = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _ecore_evas_x_event_mouse_in, NULL);
+   ecore_evas_event_handlers[1]  = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _ecore_evas_x_event_mouse_out, NULL);
+   ecore_evas_event_handlers[2]  = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _ecore_evas_x_event_window_focus_in, NULL);
+   ecore_evas_event_handlers[3]  = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _ecore_evas_x_event_window_focus_out, NULL);
+   ecore_evas_event_handlers[4]  = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, _ecore_evas_x_event_window_damage, NULL);
+   ecore_evas_event_handlers[5] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_evas_x_event_window_destroy, NULL);
+   ecore_evas_event_handlers[6] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _ecore_evas_x_event_window_configure, NULL);
+   ecore_evas_event_handlers[7] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, _ecore_evas_x_event_window_delete_request, NULL);
+   ecore_evas_event_handlers[8] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, _ecore_evas_x_event_window_show, NULL);
+   ecore_evas_event_handlers[9] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _ecore_evas_x_event_window_hide, NULL);
+   ecore_evas_event_handlers[10] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _ecore_evas_x_event_property_change, NULL);
+   ecore_evas_event_handlers[11] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, _ecore_evas_x_event_visibility_change, NULL);
+   ecore_evas_event_handlers[12] = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _ecore_evas_x_event_client_message, NULL);
+   ecore_event_evas_init();
+   return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_x_free(Ecore_Evas *ee)
+{
+   _ecore_evas_x_sync_set(ee);
+   ecore_x_window_free(ee->prop.window);
+   if (ee->engine.x.pmap) ecore_x_pixmap_free(ee->engine.x.pmap);
+   if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+   if (ee->engine.x.gc) ecore_x_gc_free(ee->engine.x.gc);
+   if (ee->engine.x.damages) ecore_x_xregion_free(ee->engine.x.damages);
+   ee->engine.x.pmap = 0;
+   ee->engine.x.mask = 0;
+   ee->engine.x.gc = 0;
+   ee->engine.x.damages = NULL;
+   ecore_event_window_unregister(ee->prop.window);
+   while (ee->engine.x.win_extra)
+     {
+       Ecore_X_Window *winp;
+
+       winp = ee->engine.x.win_extra->data;
+       ee->engine.x.win_extra = eina_list_remove_list(ee->engine.x.win_extra, ee->engine.x.win_extra);
+       ecore_event_window_unregister(*winp);
+       free(winp);
+     }
+   _ecore_evas_x_shutdown();
+   ecore_x_shutdown();
+}
+
+static void
+_ecore_evas_x_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee))
+{
+   ee->func.fn_delete_request = func;
+   _ecore_evas_x_protocols_set(ee);
+   _ecore_evas_x_sync_set(ee);
+}
+
+static void
+_ecore_evas_x_move(Ecore_Evas *ee, int x, int y)
+{
+   ee->req.x = x;
+   ee->req.y = y;
+   if (ee->engine.x.direct_resize)
+     {
+       if (!ee->engine.x.managed)
+         {
+            if ((x != ee->x) || (y != ee->y))
+              {
+                 ee->x = x;
+                 ee->y = y;
+                 ecore_x_window_move(ee->prop.window, x, y);
+                 if (!ee->should_be_visible)
+                   {
+                      /* We need to request pos */
+                      ee->prop.request_pos = 1;
+                      _ecore_evas_x_size_pos_hints_update(ee);
+                   }
+                 if (ee->func.fn_move) ee->func.fn_move(ee);
+              }
+         }
+     }
+   else
+     {
+       ecore_x_window_move(ee->prop.window, x, y);
+       if (!ee->should_be_visible)
+         {
+            /* We need to request pos */
+            ee->prop.request_pos = 1;
+            _ecore_evas_x_size_pos_hints_update(ee);
+         }
+       if (!ee->engine.x.managed)
+         {
+            ee->x = x;
+            ee->y = y;
+         }
+     }
+}
+
+static void
+_ecore_evas_x_managed_move(Ecore_Evas *ee, int x, int y)
+{
+   ee->req.x = x;
+   ee->req.y = y;
+   if (ee->engine.x.direct_resize)
+     {
+       ee->engine.x.managed = 1;
+       if ((x != ee->x) || (y != ee->y))
+         {
+            ee->x = x;
+            ee->y = y;
+            if (ee->func.fn_move) ee->func.fn_move(ee);
+         }
+     }
+}
+
+static void
+_ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
+{
+   ee->req.w = w;
+   ee->req.h = h;
+   if (ee->engine.x.direct_resize)
+     {
+       if ((ee->w != w) || (ee->h != h))
+         {
+            ecore_x_window_resize(ee->prop.window, w, h);
+            ee->w = w;
+            ee->h = h;
+            if ((ee->rotation == 90) || (ee->rotation == 270))
+              {
+                 evas_output_size_set(ee->evas, ee->h, ee->w);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+              }
+            else
+              {
+                 evas_output_size_set(ee->evas, ee->w, ee->h);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+              }
+            if (ee->prop.avoid_damage)
+              {
+                 int pdam;
+
+                 pdam = ecore_evas_avoid_damage_get(ee);
+                 ecore_evas_avoid_damage_set(ee, 0);
+                 ecore_evas_avoid_damage_set(ee, pdam);
+              }
+            if ((ee->shaped) || (ee->alpha))
+              _ecore_evas_x_resize_shape(ee);
+            if (ee->func.fn_resize) ee->func.fn_resize(ee);
+         }
+     }
+   else
+     ecore_x_window_resize(ee->prop.window, w, h);
+}
+
+static void
+_ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
+{
+   ee->req.x = x;
+   ee->req.y = y;
+   ee->req.w = w;
+   ee->req.h = h;
+   if (ee->engine.x.direct_resize)
+     {
+       if ((ee->w != w) || (ee->h != h) || (x != ee->x) || (y != ee->y))
+         {
+            int change_size = 0, change_pos = 0;
+
+            if ((ee->w != w) || (ee->h != h)) change_size = 1;
+            if (!ee->engine.x.managed)
+              {
+                 if ((x != ee->x) || (y != ee->y)) change_pos = 1;
+              }
+            ecore_x_window_move_resize(ee->prop.window, x, y, w, h);
+            if (!ee->engine.x.managed)
+              {
+                 ee->x = x;
+                 ee->y = y;
+              }
+            ee->w = w;
+            ee->h = h;
+            if ((ee->rotation == 90) || (ee->rotation == 270))
+              {
+                 evas_output_size_set(ee->evas, ee->h, ee->w);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+              }
+            else
+              {
+                 evas_output_size_set(ee->evas, ee->w, ee->h);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+              }
+            if (ee->prop.avoid_damage)
+              {
+                 int pdam;
+
+                 pdam = ecore_evas_avoid_damage_get(ee);
+                 ecore_evas_avoid_damage_set(ee, 0);
+                 ecore_evas_avoid_damage_set(ee, pdam);
+              }
+            if ((ee->shaped) || (ee->alpha))
+              _ecore_evas_x_resize_shape(ee);
+            if (change_pos)
+              {
+                 if (ee->func.fn_move) ee->func.fn_move(ee);
+              }
+            if (change_size)
+              {
+                 if (ee->func.fn_resize) ee->func.fn_resize(ee);
+              }
+         }
+     }
+   else
+     {
+       ecore_x_window_move_resize(ee->prop.window, x, y, w, h);
+       if (!ee->engine.x.managed)
+         {
+            ee->x = x;
+            ee->y = y;
+         }
+     }
+}
+
+static void
+_ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation, int resize,
+                                   Evas_Engine_Info *einfo)
+{
+   int rot_dif;
+
+   rot_dif = ee->rotation - rotation;
+   if (rot_dif < 0) rot_dif = -rot_dif;
+
+   if (rot_dif != 180)
+     {
+       int minw, minh, maxw, maxh, basew, baseh, stepw, steph;
+
+       if (!evas_engine_info_set(ee->evas, einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+
+       if (!resize)
+          {
+             if (!ee->prop.fullscreen)
+               {
+                  ecore_x_window_resize(ee->prop.window, ee->req.h, ee->req.w);
+                  ee->expecting_resize.w = ee->h;
+                  ee->expecting_resize.h = ee->w;
+               }
+             else
+               {
+                  int w, h;
+                  
+                  ecore_x_window_size_get(ee->prop.window, &w, &h);
+                  ecore_x_window_resize(ee->prop.window, h, w);
+                  if ((rotation == 0) || (rotation == 180))
+                    {
+                       evas_output_size_set(ee->evas, ee->req.w, ee->req.h);
+                       evas_output_viewport_set(ee->evas, 0, 0, ee->req.w, ee->req.h);
+                    }
+                  else
+                    {
+                       evas_output_size_set(ee->evas, ee->req.h, ee->req.w);
+                       evas_output_viewport_set(ee->evas, 0, 0, ee->req.h, ee->req.w);
+                    }
+                  if (ee->func.fn_resize) ee->func.fn_resize(ee);
+               }
+             if ((ee->rotation == 90) || (ee->rotation == 270))
+               evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.h, ee->req.w);
+             else
+               evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
+          }
+       else
+          {
+            int w, h;
+             
+            ecore_x_window_size_get(ee->prop.window, &w, &h);
+            if ((rotation == 0) || (rotation == 180))
+              {
+                 evas_output_size_set(ee->evas, ee->w, ee->h);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+              }
+            else
+              {
+                 evas_output_size_set(ee->evas, ee->h, ee->w);
+                 evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
+              }
+            if (ee->func.fn_resize) ee->func.fn_resize(ee);
+             if ((ee->rotation == 90) || (ee->rotation == 270))
+               evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+             else
+               evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+          }
+       ecore_evas_size_min_get(ee, &minw, &minh);
+       ecore_evas_size_max_get(ee, &maxw, &maxh);
+       ecore_evas_size_base_get(ee, &basew, &baseh);
+       ecore_evas_size_step_get(ee, &stepw, &steph);
+       ee->rotation = rotation;
+       ecore_evas_size_min_set(ee, minh, minw);
+       ecore_evas_size_max_set(ee, maxh, maxw);
+       ecore_evas_size_base_set(ee, baseh, basew);
+       ecore_evas_size_step_set(ee, steph, stepw);
+       _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                      ecore_x_current_time_get());
+     }
+   else
+     {
+       if (!evas_engine_info_set(ee->evas, einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       ee->rotation = rotation;
+       _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
+                                      ecore_x_current_time_get());
+       if (ee->func.fn_resize) ee->func.fn_resize(ee);
+        
+        if ((ee->rotation == 90) || (ee->rotation == 270))
+          evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+        else
+          evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+     }
+}
+
+static void
+_ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize)
+{
+   if (ee->rotation == rotation) return;
+   if (!strcmp(ee->driver, "xrender_x11")) return;
+   if (!strcmp(ee->driver, "opengl_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+       Evas_Engine_Info_GL_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+       einfo->info.rotation = rotation;
+       _ecore_evas_x_rotation_set_internal
+         (ee, rotation, resize, (Evas_Engine_Info *)einfo);
+#endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
+     }
+   else if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+       einfo->info.rotation = rotation;
+       _ecore_evas_x_rotation_set_internal
+         (ee, rotation, resize, (Evas_Engine_Info *)einfo);
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
+     }
+   else if (!strcmp(ee->driver,  "software_16_x11"))
+     {
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+       Evas_Engine_Info_Software_16_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+       einfo->info.rotation = rotation;
+       _ecore_evas_x_rotation_set_internal
+         (ee, rotation, resize, (Evas_Engine_Info *)einfo);
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+     }
+}
+
+static void
+_ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
+{
+   if (((ee->shaped) && (shaped)) || ((!ee->shaped) && (!shaped)))
+     return;
+   if (!strcmp(ee->driver, "opengl_x11")) return;
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       ee->shaped = shaped;
+       if (einfo)
+         {
+            if (ee->shaped)
+              {
+                  unsigned int    foreground;
+                  Ecore_X_GC      gc;
+
+                 if (!ee->engine.x.mask)
+                   ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+                  foreground = 0;
+                  gc = ecore_x_gc_new(ee->engine.x.mask,
+                                      ECORE_X_GC_VALUE_MASK_FOREGROUND,
+                                      &foreground);
+                  ecore_x_drawable_rectangle_fill(ee->engine.x.mask, gc,
+                                                  0, 0, ee->w, ee->h);
+                  ecore_x_gc_free(gc);
+                 einfo->info.mask = ee->engine.x.mask;
+                 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+                 ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+              }
+            else
+              {
+                 if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+                 ee->engine.x.mask = 0;
+                 einfo->info.mask = 0;
+                 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+                 ecore_x_window_shape_mask_set(ee->prop.window, 0);
+                 ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+              }
+         }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
+     }
+   else if (!strcmp(ee->driver, "xrender_x11"))
+     {
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+       Evas_Engine_Info_XRender_X11 *einfo;
+
+       ee->shaped = shaped;
+       einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            if (ee->shaped)
+              {
+                  unsigned int    foreground;
+                  Ecore_X_GC      gc;
+
+                 if (!ee->engine.x.mask)
+                   ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+                  foreground = 0;
+                  gc = ecore_x_gc_new(ee->engine.x.mask,
+                                      ECORE_X_GC_VALUE_MASK_FOREGROUND,
+                                      &foreground);
+                  ecore_x_drawable_rectangle_fill(ee->engine.x.mask, gc,
+                                                  0, 0, ee->w, ee->h);
+                  ecore_x_gc_free(gc);
+                 einfo->info.mask = ee->engine.x.mask;
+                 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+                 ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+              }
+            else
+              {
+                 if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+                 ee->engine.x.mask = 0;
+                 einfo->info.mask = 0;
+                 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 ecore_x_window_shape_mask_set(ee->prop.window, 0);
+                 ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+              }
+         }
+#endif /* BUILD_ECORE_EVAS_XRENDER_X11 || BUILD_ECORE_EVAS_XRENDER_XCB */
+     }
+   else if (!strcmp(ee->driver, "software_16_x11"))
+     {
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+# if 0 /* XXX no shaped window support for software_16_x11 */
+       Evas_Engine_Info_Software_16_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+       ee->shaped = shaped;
+       if (einfo)
+         {
+            if (ee->shaped)
+              {
+                 GC gc;
+                 XGCValues gcv;
+
+                 ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
+                 einfo->info.mask = ee->engine.x.mask;
+                 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+              }
+            else
+              {
+                 if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+                 ee->engine.x.mask = 0;
+                 einfo->info.mask = 0;
+                 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 ecore_x_window_shape_mask_set(ee->prop.window, 0);
+              }
+         }
+# endif /* XXX no shaped window support for software_16_x11 */
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+     }
+
+}
+
+/* FIXME, round trip */
+static void
+_ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
+{
+# ifdef HAVE_ECORE_X_XCB
+   xcb_get_geometry_cookie_t          cookie_geom;
+   xcb_get_window_attributes_cookie_t cookie_attr;
+   xcb_get_geometry_reply_t          *reply_geom;
+   xcb_get_window_attributes_reply_t *reply_attr;
+#else
+   XWindowAttributes att;
+#endif /* ! HAVE_ECORE_X_XCB */
+
+   if (((ee->alpha) && (alpha)) || ((!ee->alpha) && (!alpha)))
+     return;
+
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+
+       if (!ecore_x_composite_query()) return;
+
+       ee->shaped = 0;
+       ee->alpha = alpha;
+       ecore_x_window_free(ee->prop.window);
+       ecore_event_window_unregister(ee->prop.window);
+       if (ee->alpha)
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (!ee->engine.x.mask)
+              ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
+         }
+       else
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = 0;
+            ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+         }
+
+       einfo->info.destination_alpha = alpha;
+
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+       cookie_geom = xcb_get_geometry_unchecked(ecore_x_connection_get(), ee->prop.window);
+       cookie_attr = xcb_get_window_attributes_unchecked(ecore_x_connection_get(), ee->prop.window);
+
+       reply_geom = xcb_get_geometry_reply(ecore_x_connection_get(), cookie_geom, NULL);
+       reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL);
+       einfo->info.visual = xcb_visualtype_get(ecore_x_default_screen_get(), reply_attr->visual);
+       einfo->info.colormap = reply_attr->colormap;
+       einfo->info.depth = reply_geom->depth;
+       free(reply_geom);
+       free(reply_attr);
+# else
+       XGetWindowAttributes(ecore_x_display_get(), ee->prop.window, &att);
+       einfo->info.visual = att.visual;
+       einfo->info.colormap = att.colormap;
+       einfo->info.depth = att.depth;
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+
+//     if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+//     ee->engine.x.mask = 0;
+       einfo->info.mask = ee->engine.x.mask;
+       einfo->info.drawable = ee->prop.window;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
+       ecore_x_window_shape_mask_set(ee->prop.window, 0);
+        ecore_x_input_multi_select(ee->prop.window);
+       ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+       if (ee->prop.borderless)
+         ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
+       if (ee->visible) ecore_x_window_show(ee->prop.window);
+       if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+       if (ee->prop.title)
+         {
+            ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
+            ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
+         }
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+        _ecore_evas_x_protocols_set(ee);
+        _ecore_evas_x_sync_set(ee);
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
+        if (getenv("DESKTOP_STARTUP_ID"))
+          {
+             ecore_x_netwm_startup_id_set(ee->prop.window,
+                                          getenv("DESKTOP_STARTUP_ID"));
+             /* NB: on linux this may simply empty the env as opposed to completely
+              * unset it to being empty - unsure as solartis libc crashes looking
+              * for the '=' char */
+             //        putenv((char*)"DESKTOP_STARTUP_ID=");
+          }
+     }
+   else if (!strcmp(ee->driver, "opengl_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+       Evas_Engine_Info_GL_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+
+       if (!ecore_x_composite_query()) return;
+
+       ee->shaped = 0;
+       ee->alpha = alpha;
+       ecore_x_window_free(ee->prop.window);
+       ecore_event_window_unregister(ee->prop.window);
+        ee->prop.window = 0;
+        
+       einfo->info.destination_alpha = alpha;
+        
+        if (ee->engine.x.win_root != 0)
+          {
+             /* FIXME: round trip in ecore_x_window_argb_get */
+             if (ecore_x_window_argb_get(ee->engine.x.win_root))
+               {
+                  ee->prop.window = _ecore_evas_x_gl_window_new
+                    (ee, ee->engine.x.win_root, 
+                     ee->req.x, ee->req.y, ee->req.w, ee->req.h,
+                     ee->prop.override, 1, NULL);
+               }
+             else
+               ee->prop.window = _ecore_evas_x_gl_window_new
+               (ee, ee->engine.x.win_root,
+                ee->req.x, ee->req.y, ee->req.w, ee->req.h,
+                ee->prop.override, ee->alpha, NULL);
+          }
+        else
+          ee->prop.window = _ecore_evas_x_gl_window_new
+          (ee, ee->engine.x.win_root, 
+           ee->req.x, ee->req.y, ee->req.w, ee->req.h,
+           ee->prop.override, ee->alpha, NULL);
+        if (!ee->prop.window)
+          {
+             return;
+          }
+/*        
+       if (ee->alpha)
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (!ee->engine.x.mask)
+              ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
+         }
+       else
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = 0;
+            ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+         }
+ */
+
+       XGetWindowAttributes(ecore_x_display_get(), ee->prop.window, &att);
+       einfo->info.visual = att.visual;
+       einfo->info.colormap = att.colormap;
+       einfo->info.depth = att.depth;
+
+//     if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+//     ee->engine.x.mask = 0;
+//     einfo->info.mask = ee->engine.x.mask;
+       einfo->info.drawable = ee->prop.window;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
+//     ecore_x_window_shape_mask_set(ee->prop.window, 0);
+        ecore_x_input_multi_select(ee->prop.window);
+       ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+       if (ee->prop.borderless)
+         ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
+       if (ee->visible) ecore_x_window_show(ee->prop.window);
+       if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+       if (ee->prop.title)
+         {
+            ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
+            ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
+         }
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+        _ecore_evas_x_protocols_set(ee);
+        _ecore_evas_x_sync_set(ee);
+#endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
+        if (getenv("DESKTOP_STARTUP_ID"))
+          {
+             ecore_x_netwm_startup_id_set(ee->prop.window,
+                                          getenv("DESKTOP_STARTUP_ID"));
+             /* NB: on linux this may simply empty the env as opposed to completely
+              * unset it to being empty - unsure as solartis libc crashes looking
+              * for the '=' char */
+             //        putenv((char*)"DESKTOP_STARTUP_ID=");
+          }
+     }
+   else if (!strcmp(ee->driver, "xrender_x11"))
+     {
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+       Evas_Engine_Info_XRender_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+       if (!ecore_x_composite_query()) return;
+
+       ee->shaped = 0;
+       ee->alpha = alpha;
+       ecore_x_window_free(ee->prop.window);
+       ecore_event_window_unregister(ee->prop.window);
+       if (ee->alpha)
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (!ee->engine.x.mask)
+              ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
+         }
+       else
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = 0;
+            ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+         }
+
+       einfo->info.destination_alpha = alpha;
+
+# ifdef BUILD_ECORE_EVAS_XRENDER_XCB
+       cookie_attr = xcb_get_window_attributes_unchecked(ecore_x_connection_get(), ee->prop.window);
+       reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL);
+
+       einfo->info.visual = reply_attr->visual;
+       free(reply_attr);
+# else
+       XGetWindowAttributes(ecore_x_display_get(), ee->prop.window, &att);
+       einfo->info.visual = att.visual;
+# endif /* ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+//     if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+//     ee->engine.x.mask = 0;
+        einfo->info.mask = ee->engine.x.mask;
+       einfo->info.drawable = ee->prop.window;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
+       ecore_x_window_shape_mask_set(ee->prop.window, 0);
+        ecore_x_input_multi_select(ee->prop.window);
+       ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+       if (ee->prop.borderless)
+         ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
+       if (ee->visible) ecore_x_window_show(ee->prop.window);
+       if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+       if (ee->prop.title)
+         {
+            ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
+            ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
+         }
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+        _ecore_evas_x_protocols_set(ee);
+        _ecore_evas_x_sync_set(ee);
+#endif /* BUILD_ECORE_EVAS_XRENDER_X11 || BUILD_ECORE_EVAS_XRENDER_XCB */
+        if (getenv("DESKTOP_STARTUP_ID"))
+          {
+             ecore_x_netwm_startup_id_set(ee->prop.window,
+                                          getenv("DESKTOP_STARTUP_ID"));
+             /* NB: on linux this may simply empty the env as opposed to completely
+              * unset it to being empty - unsure as solartis libc crashes looking
+              * for the '=' char */
+             //        putenv((char*)"DESKTOP_STARTUP_ID=");
+          }
+     }
+   else if (!strcmp(ee->driver, "software_16_x11"))
+     {
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+       Evas_Engine_Info_Software_16_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+
+       ee->shaped = 0;
+       ee->alpha = alpha;
+       ecore_x_window_free(ee->prop.window);
+       ecore_event_window_unregister(ee->prop.window);
+       if (ee->alpha)
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_argb_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (!ee->engine.x.mask)
+              ee->engine.x.mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
+         }
+       else
+         {
+            if (ee->prop.override)
+              ee->prop.window = ecore_x_window_override_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            else
+              ee->prop.window = ecore_x_window_new(ee->engine.x.win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
+            if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+            ee->engine.x.mask = 0;
+            ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
+         }
+
+# if 0 /* XXX no alpha window support for software_16_x11 */
+       einfo->info.destination_alpha = alpha;
+# endif /* XXX no alpha window support for software_16_x11 */
+
+# if 0 /* XXX no shaped window support for software_16_x11 */
+//     if (ee->engine.x.mask) ecore_x_pixmap_free(ee->engine.x.mask);
+//     ee->engine.x.mask = 0;
+        einfo->info.mask = ee->engine.x.mask;
+# endif /* XXX no shaped window support for software_16_x11 */
+
+       einfo->info.drawable = ee->prop.window;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
+       ecore_x_window_shape_mask_set(ee->prop.window, 0);
+        ecore_x_input_multi_select(ee->prop.window);
+       ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+       if (ee->prop.borderless)
+         ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
+       if (ee->visible) ecore_x_window_show(ee->prop.window);
+       if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+       if (ee->prop.title)
+         {
+            ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
+            ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
+         }
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+        _ecore_evas_x_protocols_set(ee);
+        _ecore_evas_x_sync_set(ee);
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+        if (getenv("DESKTOP_STARTUP_ID"))
+          {
+             ecore_x_netwm_startup_id_set(ee->prop.window,
+                                          getenv("DESKTOP_STARTUP_ID"));
+             /* NB: on linux this may simply empty the env as opposed to completely
+              * unset it to being empty - unsure as solartis libc crashes looking
+              * for the '=' char */
+             //        putenv((char*)"DESKTOP_STARTUP_ID=");
+          }
+     }
+}
+
+static void
+_ecore_evas_x_transparent_set(Ecore_Evas *ee, int transparent)
+{
+   if (((ee->transparent) && (transparent)) || 
+       ((!ee->transparent) && (!transparent)))
+     return;
+
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (!einfo) return;
+
+       ee->transparent = transparent;
+       einfo->info.destination_alpha = transparent;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+       evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+#endif        
+     }
+}
+#endif /* BUILD_ECORE_EVAS_X11 */
+
+#ifdef BUILD_ECORE_EVAS_X11
+static void
+_ecore_evas_x_show(Ecore_Evas *ee)
+{
+   ee->should_be_visible = 1;
+   if (ee->prop.avoid_damage)
+     _ecore_evas_x_render(ee);
+   ecore_x_window_show(ee->prop.window);
+   if (ee->prop.fullscreen)
+     ecore_x_window_focus(ee->prop.window);
+}
+
+static void
+_ecore_evas_x_hide(Ecore_Evas *ee)
+{
+   ecore_x_window_hide(ee->prop.window);
+   ee->should_be_visible = 0;
+}
+
+static void
+_ecore_evas_x_raise(Ecore_Evas *ee)
+{
+   if (!ee->prop.fullscreen)
+     ecore_x_window_raise(ee->prop.window);
+   else
+     ecore_x_window_raise(ee->prop.window);
+}
+
+static void
+_ecore_evas_x_lower(Ecore_Evas *ee)
+{
+   if (!ee->prop.fullscreen)
+     ecore_x_window_lower(ee->prop.window);
+   else
+     ecore_x_window_lower(ee->prop.window);
+}
+
+static void
+_ecore_evas_x_activate(Ecore_Evas *ee)
+{
+   ecore_x_netwm_client_active_request(ee->engine.x.win_root,
+                                      ee->prop.window, 2, 0);
+}
+
+static void
+_ecore_evas_x_title_set(Ecore_Evas *ee, const char *t)
+{
+   if (ee->prop.title) free(ee->prop.title);
+   ee->prop.title = NULL;
+   if (t) ee->prop.title = strdup(t);
+   ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
+   ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
+}
+
+static void
+_ecore_evas_x_name_class_set(Ecore_Evas *ee, const char *n, const char *c)
+{
+   if (ee->prop.name) free(ee->prop.name);
+   if (ee->prop.clas) free(ee->prop.clas);
+   ee->prop.name = NULL;
+   ee->prop.clas = NULL;
+   if (n) ee->prop.name = strdup(n);
+   if (c) ee->prop.clas = strdup(c);
+   ecore_x_icccm_name_class_set(ee->prop.window, ee->prop.name, ee->prop.clas);
+}
+
+static void
+_ecore_evas_x_size_min_set(Ecore_Evas *ee, int w, int h)
+{
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->prop.min.w == w) && (ee->prop.min.h == h)) return;
+   ee->prop.min.w = w;
+   ee->prop.min.h = h;
+   _ecore_evas_x_size_pos_hints_update(ee);
+}
+
+static void
+_ecore_evas_x_size_max_set(Ecore_Evas *ee, int w, int h)
+{
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->prop.max.w == w) && (ee->prop.max.h == h)) return;
+   ee->prop.max.w = w;
+   ee->prop.max.h = h;
+   _ecore_evas_x_size_pos_hints_update(ee);
+}
+
+static void
+_ecore_evas_x_size_base_set(Ecore_Evas *ee, int w, int h)
+{
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+   if ((ee->prop.base.w == w) && (ee->prop.base.h == h)) return;
+   ee->prop.base.w = w;
+   ee->prop.base.h = h;
+   _ecore_evas_x_size_pos_hints_update(ee);
+}
+
+static void
+_ecore_evas_x_size_step_set(Ecore_Evas *ee, int w, int h)
+{
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   if ((ee->prop.step.w == w) && (ee->prop.step.h == h)) return;
+   ee->prop.step.w = w;
+   ee->prop.step.h = h;
+   _ecore_evas_x_size_pos_hints_update(ee);
+}
+
+static void
+_ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee)
+     ee->prop.cursor.object = NULL;
+}
+
+static void
+_ecore_evas_x_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
+{
+   int x, y;
+
+   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
+
+   if (obj == NULL)
+     {
+       ee->prop.cursor.object = NULL;
+       ee->prop.cursor.layer = 0;
+       ee->prop.cursor.hot.x = 0;
+       ee->prop.cursor.hot.y = 0;
+       ecore_x_window_cursor_show(ee->prop.window, 1);
+       return;
+     }
+
+   ee->prop.cursor.object = obj;
+   ee->prop.cursor.layer = layer;
+   ee->prop.cursor.hot.x = hot_x;
+   ee->prop.cursor.hot.y = hot_y;
+
+   ecore_x_window_cursor_show(ee->prop.window, 0);
+
+   evas_pointer_output_xy_get(ee->evas, &x, &y);
+   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   evas_object_move(ee->prop.cursor.object,
+                   x - ee->prop.cursor.hot.x,
+                   y - ee->prop.cursor.hot.y);
+   evas_object_pass_events_set(ee->prop.cursor.object, 1);
+   if (evas_pointer_inside_get(ee->evas))
+     evas_object_show(ee->prop.cursor.object);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+}
+
+/*
+ * @param ee
+ * @param layer If < 3, @a ee will be put below all other windows.
+ *              If > 5, @a ee will be "always-on-top"
+ *              If = 4, @a ee will be put in the default layer.
+ *              Acceptable values range from 1 to 255 (0 reserved for
+ *              desktop windows)
+ */
+static void
+_ecore_evas_x_layer_set(Ecore_Evas *ee, int layer)
+{
+   if (ee->prop.layer == layer) return;
+
+   /* FIXME: Should this logic be here? */
+   if (layer < 1)
+     layer = 1;
+   else if (layer > 255)
+     layer = 255;
+
+   ee->prop.layer = layer;
+   _ecore_evas_x_layer_update(ee);
+}
+
+static void
+_ecore_evas_x_focus_set(Ecore_Evas *ee, int on __UNUSED__)
+{
+   ecore_x_window_focus(ee->prop.window);
+}
+
+static void
+_ecore_evas_x_iconified_set(Ecore_Evas *ee, int on)
+{
+//   if (((ee->prop.iconified) && (on)) ||
+//       ((!ee->prop.iconified) && (!on))) return;
+   ee->prop.iconified = on;
+   if (on)
+     {
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_ICONIC /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+       ecore_x_icccm_iconic_request_send(ee->prop.window, ee->engine.x.win_root);
+     }
+   else
+     {
+       ecore_x_icccm_hints_set(ee->prop.window,
+                               1 /* accepts_focus */,
+                               ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                               0 /* icon_pixmap */,
+                               0 /* icon_mask */,
+                               0 /* icon_window */,
+                               0 /* window_group */,
+                               0 /* is_urgent */);
+       ecore_evas_show(ee);
+     }
+}
+
+static void
+_ecore_evas_x_borderless_set(Ecore_Evas *ee, int on)
+{
+   if (((ee->prop.borderless) && (on)) ||
+       ((!ee->prop.borderless) && (!on))) return;
+   ee->prop.borderless = on;
+   ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
+}
+
+/* FIXME: This function changes the initial state of the ee
+ * whilest the iconic function changes the current state! */
+static void
+_ecore_evas_x_withdrawn_set(Ecore_Evas *ee, int withdrawn)
+{
+   Ecore_X_Window_State_Hint hint;
+
+   if ((ee->prop.withdrawn && withdrawn) ||
+      (!ee->prop.withdrawn && !withdrawn)) return;
+
+   ee->prop.withdrawn = withdrawn;
+   if (withdrawn)
+     hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
+   else
+     hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+
+   ecore_x_icccm_hints_set(ee->prop.window,
+                          1 /* accepts_focus */,
+                          hint /* initial_state */,
+                          0 /* icon_pixmap */,
+                          0 /* icon_mask */,
+                          0 /* icon_window */,
+                          0 /* window_group */,
+                          0 /* is_urgent */);
+}
+
+static void
+_ecore_evas_x_sticky_set(Ecore_Evas *ee, int sticky)
+{
+   if ((ee->prop.sticky && sticky) ||
+      (!ee->prop.sticky && !sticky)) return;
+
+   /* We dont want to set prop.sticky here as it will cause
+    * the sticky callback not to get called. Its set on the
+    * property change event.
+    * ee->prop.sticky = sticky;
+    */
+   ee->engine.x.state.sticky = sticky;
+   if (ee->should_be_visible)
+     ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root,
+                                     ECORE_X_WINDOW_STATE_STICKY, -1, sticky);
+   else
+     _ecore_evas_x_state_update(ee);
+}
+
+static void
+_ecore_evas_x_ignore_events_set(Ecore_Evas *ee, int ignore)
+{
+   if ((ee->ignore_events && ignore) ||
+       (!ee->ignore_events && !ignore)) return;
+
+   if (ignore)
+     {
+       ee->ignore_events = 1;
+       if (ee->prop.window)
+         ecore_x_window_ignore_set(ee->prop.window, 1);
+     }
+   else
+     {
+       ee->ignore_events = 0;
+       if (ee->prop.window)
+         ecore_x_window_ignore_set(ee->prop.window, 0);
+     }
+}
+
+/*
+static void
+_ecore_evas_x_reinit_win(Ecore_Evas *ee)
+{
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            einfo->info.drawable = ee->prop.window;
+            evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+         }
+#endif
+     }
+   else if (!strcmp(ee->driver, "xrender_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_XRENDER_X11
+       Evas_Engine_Info_XRender_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            einfo->info.drawable = ee->prop.window;
+            evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+         }
+#endif
+     }
+   else if (!strcmp(ee->driver, "opengl_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+       Evas_Engine_Info_GL_X11 *einfo;
+
+       einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            einfo->info.drawable = ee->prop.window;
+            evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+         }
+#endif
+     }
+}
+*/
+
+static void
+_ecore_evas_x_override_set(Ecore_Evas *ee, int on)
+{
+   if (((ee->prop.override) && (on)) ||
+       ((!ee->prop.override) && (!on))) return;
+   ecore_x_window_hide(ee->prop.window);
+   ecore_x_window_override_set(ee->prop.window, on);
+   if (ee->visible) ecore_x_window_show(ee->prop.window);
+   if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+   ee->prop.override = on;
+}
+
+static void
+_ecore_evas_x_fullscreen_set(Ecore_Evas *ee, int on)
+{
+   if ((ee->prop.fullscreen && on) ||
+      (!ee->prop.fullscreen && !on)) return;
+
+   /* FIXME: Detect if WM is EWMH compliant and handle properly if not,
+    * i.e. reposition, resize, and change borderless hint */
+   ee->engine.x.state.fullscreen = on;
+   if (ee->should_be_visible)
+     ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root,
+                                     ECORE_X_WINDOW_STATE_FULLSCREEN, -1, on);
+   else
+     _ecore_evas_x_state_update(ee);
+}
+
+static void
+_ecore_evas_x_avoid_damage_set(Ecore_Evas *ee, int on)
+{
+   if (ee->prop.avoid_damage == on) return;
+   if (!strcmp(ee->driver, "opengl_x11")) return;
+   if (!strcmp(ee->driver, "xrender_x11")) return;
+
+   if (!strcmp(ee->driver, "software_x11"))
+     {
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+       Evas_Engine_Info_Software_X11 *einfo;
+
+       ee->prop.avoid_damage = on;
+       einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            if (ee->prop.avoid_damage)
+              {
+                 ee->engine.x.pmap = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, einfo->info.depth);
+                 ee->engine.x.gc = ecore_x_gc_new(ee->engine.x.pmap, 0, NULL);
+                 einfo->info.drawable = ee->engine.x.pmap;
+                  if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 if ((ee->rotation == 90) || (ee->rotation == 270))
+                   evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+                 else
+                   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+                 if (ee->prop.avoid_damage == ECORE_EVAS_AVOID_DAMAGE_BUILT_IN)
+                   {
+                      ee->engine.x.using_bg_pixmap = 1;
+                      ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
+                      ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
+                   }
+                 if (ee->engine.x.direct_resize)
+                   {
+                      /* Turn this off for now
+                         ee->engine.x.using_bg_pixmap = 1;
+                         ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
+                      */
+                   }
+              }
+            else
+              {
+                 if (ee->engine.x.pmap) ecore_x_pixmap_free(ee->engine.x.pmap);
+                 if (ee->engine.x.gc) ecore_x_gc_free(ee->engine.x.gc);
+                 if (ee->engine.x.using_bg_pixmap)
+                   {
+                      ecore_x_window_pixmap_set(ee->prop.window, 0);
+                      ee->engine.x.using_bg_pixmap = 0;
+                      ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
+                   }
+                 ee->engine.x.pmap = 0;
+                 ee->engine.x.gc = 0;
+                 einfo->info.drawable = ee->prop.window;
+                  if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+              }
+         }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
+     }
+   else if (!strcmp(ee->driver, "software_16_x11"))
+     {
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+       Evas_Engine_Info_Software_16_X11 *einfo;
+       ee->prop.avoid_damage = on;
+
+       einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+       if (einfo)
+         {
+            if (ee->prop.avoid_damage)
+              {
+                 ee->engine.x.pmap = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 16);
+                 ee->engine.x.gc = ecore_x_gc_new(ee->engine.x.pmap, 0, NULL);
+                 einfo->info.drawable = ee->engine.x.pmap;
+                  if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+                 if ((ee->rotation == 90) || (ee->rotation == 270))
+                   evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
+                 else
+                   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+                 if (ee->engine.x.direct_resize)
+                   {
+                      /* Turn this off for now
+                         ee->engine.x.using_bg_pixmap = 1;
+                         ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
+                      */
+                   }
+              }
+            else
+              {
+                 if (ee->engine.x.pmap) ecore_x_pixmap_free(ee->engine.x.pmap);
+                 if (ee->engine.x.gc) ecore_x_gc_free(ee->engine.x.gc);
+                 if (ee->engine.x.using_bg_pixmap)
+                   {
+                      ecore_x_window_pixmap_set(ee->prop.window, 0);
+                      ee->engine.x.using_bg_pixmap = 0;
+                   }
+                 ee->engine.x.pmap = 0;
+                 ee->engine.x.gc = 0;
+                 einfo->info.drawable = ee->prop.window;
+                  if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                    {
+                       ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                    }
+              }
+         }
+#endif /* BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+     }
+}
+
+int
+_ecore_evas_x_shutdown(void)
+{
+   _ecore_evas_init_count--;
+   if (_ecore_evas_init_count == 0)
+     {
+       unsigned int i;
+
+       for (i = 0; i < sizeof(ecore_evas_event_handlers) / sizeof(Ecore_Event_Handler*); i++)
+          {
+             if (ecore_evas_event_handlers[i])
+               ecore_event_handler_del(ecore_evas_event_handlers[i]);
+          }
+       ecore_event_evas_shutdown();
+     }
+   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+   return _ecore_evas_init_count;
+}
+
+static Ecore_Evas_Engine_Func _ecore_x_engine_func =
+{
+   _ecore_evas_x_free,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_x_callback_delete_request_set,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_x_move,
+     _ecore_evas_x_managed_move,
+     _ecore_evas_x_resize,
+     _ecore_evas_x_move_resize,
+     _ecore_evas_x_rotation_set,
+     _ecore_evas_x_shaped_set,
+     _ecore_evas_x_show,
+     _ecore_evas_x_hide,
+     _ecore_evas_x_raise,
+     _ecore_evas_x_lower,
+     _ecore_evas_x_activate,
+     _ecore_evas_x_title_set,
+     _ecore_evas_x_name_class_set,
+     _ecore_evas_x_size_min_set,
+     _ecore_evas_x_size_max_set,
+     _ecore_evas_x_size_base_set,
+     _ecore_evas_x_size_step_set,
+     _ecore_evas_x_object_cursor_set,
+     _ecore_evas_x_layer_set,
+     _ecore_evas_x_focus_set,
+     _ecore_evas_x_iconified_set,
+     _ecore_evas_x_borderless_set,
+     _ecore_evas_x_override_set,
+     NULL,
+     _ecore_evas_x_fullscreen_set,
+     _ecore_evas_x_avoid_damage_set,
+     _ecore_evas_x_withdrawn_set,
+     _ecore_evas_x_sticky_set,
+     _ecore_evas_x_ignore_events_set,
+     _ecore_evas_x_alpha_set,
+     _ecore_evas_x_transparent_set,
+     
+     NULL // render
+};
+#endif /* BUILD_ECORE_EVAS_X11 */
+
+/*
+ * FIXME: there are some round trips. Especially, we can split
+ * ecore_x_init in 2 functions and supress some round trips.
+ */
+
+#if defined (BUILD_ECORE_EVAS_SOFTWARE_X11) || defined (BUILD_ECORE_EVAS_OPENGL_X11) || defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB) || defined (BUILD_ECORE_EVAS_SOFTWARE_16_X11)
+static void
+_ecore_evas_x_flush_pre(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+
+   if (ee->no_comp_sync) return;
+   if (!_ecore_evas_app_comp_sync) return;
+   if (ee->engine.x.sync_counter)
+     {
+        if (ee->engine.x.sync_began)
+          {
+             ee->engine.x.sync_val++;
+             if (!ee->engine.x.sync_cancel)
+               {
+                  ecore_x_sync_counter_val_wait(ee->engine.x.sync_counter,
+                                                ee->engine.x.sync_val);
+               }
+          }
+     }
+}
+
+static void
+_ecore_evas_x_flush_post(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__)
+{
+   Ecore_Evas *ee = data;
+   
+   if (ee->no_comp_sync) return;
+   if (!_ecore_evas_app_comp_sync) return;
+   if (ee->engine.x.sync_counter)
+     {
+        if (ee->engine.x.sync_began)
+          {
+             if (!ee->engine.x.sync_cancel)
+               {
+                  ecore_x_e_comp_sync_draw_done_send(ee->engine.x.win_root, 
+                                                     ee->prop.window);
+               }
+          }
+     }
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+EAPI Ecore_Evas *
+ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent,
+                           int x, int y, int w, int h)
+{
+   Evas_Engine_Info_Software_X11 *einfo;
+   Ecore_Evas *ee;
+   int argb = 0;
+   int rmethod;
+   static int redraw_debug = -1;
+
+   rmethod = evas_render_method_lookup("software_x11");
+   if (!rmethod) return NULL;
+   if (!ecore_x_init(disp_name)) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_x_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
+
+   ee->driver = "software_x11";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = w;
+   ee->h = h;
+   ee->req.x = ee->x;
+   ee->req.y = ee->y;
+   ee->req.w = ee->w;
+   ee->req.h = ee->h;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   ee->engine.x.state.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, _ecore_evas_x_flush_pre, ee);
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _ecore_evas_x_flush_post, ee);
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   ee->engine.x.win_root = parent;
+   ee->engine.x.screen_num = 0;
+   
+   if (parent != 0)
+     {
+        ee->engine.x.screen_num = 1; /* FIXME: get real scren # */
+       /* FIXME: round trip in ecore_x_window_argb_get */
+       if (ecore_x_window_argb_get(parent))
+         {
+            ee->prop.window = ecore_x_window_argb_new(parent, x, y, w, h);
+            argb = 1;
+         }
+       else
+         ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
+     }
+   else
+     ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
+   if (getenv("DESKTOP_STARTUP_ID"))
+     {
+       ecore_x_netwm_startup_id_set(ee->prop.window,
+                                    getenv("DESKTOP_STARTUP_ID"));
+       /* NB: on linux this may simply empty the env as opposed to completely
+        * unset it to being empty - unsure as solartis libc crashes looking
+        * for the '=' char */
+//     putenv((char*)"DESKTOP_STARTUP_ID=");
+     }
+   einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+        xcb_screen_iterator_t iter;
+       xcb_screen_t         *screen;
+# else
+       int screen;
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+
+       /* FIXME: this is inefficient as its a round trip */
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+       screen = ecore_x_default_screen_get();
+        iter = xcb_setup_roots_iterator (xcb_get_setup (ecore_x_connection_get()));
+       if (iter.rem > 1)
+         {
+             xcb_get_geometry_cookie_t cookie;
+             xcb_get_geometry_reply_t *reply;
+            Ecore_X_Window           *roots;
+            int                       num;
+            uint8_t                   i;
+
+            num = 0;
+             cookie = xcb_get_geometry_unchecked(ecore_x_connection_get(), parent);
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                  reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL);
+
+                 if (reply)
+                   {
+                      for (i = 0; i < num; xcb_screen_next (&iter), i++)
+                        {
+                           if (reply->root == roots[i])
+                             {
+                                screen = iter.data;
+                                break;
+                             }
+                        }
+                       free(reply);
+                   }
+                 free(roots);
+              }
+             else
+               {
+                  reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL);
+                  if (reply) free(reply);
+               }
+         }
+# else
+       screen = DefaultScreen(ecore_x_display_get());
+       if (ScreenCount(ecore_x_display_get()) > 1)
+         {
+            Ecore_X_Window *roots;
+            int num, i;
+
+            num = 0;
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                 XWindowAttributes at;
+
+                 if (XGetWindowAttributes(ecore_x_display_get(),
+                                          parent, &at))
+                   {
+                      for (i = 0; i < num; i++)
+                        {
+                           if (at.root == roots[i])
+                             {
+                                screen = i;
+                                break;
+                             }
+                        }
+                   }
+                 free(roots);
+              }
+         }
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+
+       if (redraw_debug < 0)
+         {
+            if (getenv("REDRAW_DEBUG"))
+              redraw_debug = atoi(getenv("REDRAW_DEBUG"));
+            else
+              redraw_debug = 0;
+         }
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+        einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XCB;
+       einfo->info.connection = ecore_x_connection_get();
+       einfo->info.screen = screen;
+# else
+        einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB;
+       einfo->info.connection = ecore_x_display_get();
+       einfo->info.screen = NULL;
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+       einfo->info.drawable = ee->prop.window;
+       if (argb)
+         {
+       /* FIXME: round trip */
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+             xcb_get_geometry_cookie_t          cookie_geom;
+             xcb_get_window_attributes_cookie_t cookie_attr;
+             xcb_get_geometry_reply_t          *reply_geom;
+             xcb_get_window_attributes_reply_t *reply_attr;
+
+            cookie_geom = xcb_get_geometry_unchecked(ecore_x_connection_get(), ee->prop.window);
+            cookie_attr = xcb_get_window_attributes_unchecked(ecore_x_connection_get(), ee->prop.window);
+
+             reply_geom = xcb_get_geometry_reply(ecore_x_connection_get(), cookie_geom, NULL);
+             reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL);
+            if (reply_attr && reply_geom)
+              {
+                  einfo->info.visual   = xcb_visualtype_get(ecore_x_default_screen_get(), reply_attr->visual);
+                 einfo->info.colormap = reply_attr->colormap;
+                 einfo->info.depth    = reply_geom->depth;
+                 einfo->info.destination_alpha = 1;
+                  free(reply_geom);
+                  free(reply_attr);
+              }
+# else
+            XWindowAttributes at;
+
+            if (XGetWindowAttributes(ecore_x_display_get(), ee->prop.window,
+                                     &at))
+              {
+                 einfo->info.visual   = at.visual;
+                 einfo->info.colormap = at.colormap;
+                 einfo->info.depth    = at.depth;
+                 einfo->info.destination_alpha = 1;
+              }
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+         }
+       else
+         {
+# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
+             xcb_screen_t *screen;
+
+             screen = ecore_x_default_screen_get();
+            einfo->info.visual   = xcb_visualtype_get(screen, screen->root_visual);
+            einfo->info.colormap = screen->default_colormap;
+            einfo->info.depth    = screen->root_depth;
+#else
+            einfo->info.visual   = DefaultVisual(ecore_x_display_get(), screen);
+            einfo->info.colormap = DefaultColormap(ecore_x_display_get(), screen);
+            einfo->info.depth    = DefaultDepth(ecore_x_display_get(), screen);
+# endif /* ! BUILD_ECORE_EVAS_SOFTWARE_XCB */
+            einfo->info.destination_alpha = 0;
+         }
+       einfo->info.rotation = 0;
+       einfo->info.debug    = redraw_debug;
+        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             WRN("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+             ecore_evas_free(ee);
+             return NULL;
+          }
+     }
+   ecore_x_icccm_hints_set(ee->prop.window,
+                           1 /* accepts_focus */,
+                           ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                           0 /* icon_pixmap */,
+                           0 /* icon_mask */,
+                           0 /* icon_window */,
+                           0 /* window_group */,
+                           0 /* is_urgent */);
+
+   ee->engine.func->fn_render = _ecore_evas_x_render;
+   _ecore_evas_register(ee);
+   ecore_x_input_multi_select(ee->prop.window);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_software_x11_new(const char *disp_name __UNUSED__, Ecore_X_Window parent __UNUSED__,
+                           int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+EAPI Ecore_X_Window
+ecore_evas_software_x11_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_X_Window) ecore_evas_window_get(ee);
+}
+#else
+EAPI Ecore_X_Window
+ecore_evas_software_x11_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+EAPI void
+ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on)
+{
+   ee->engine.x.direct_resize = on;
+   if (ee->prop.avoid_damage)
+     {
+       if (ee->engine.x.direct_resize)
+         {
+/* turn this off for now
+            ee->engine.x.using_bg_pixmap = 1;
+            ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
+ */
+         }
+       else
+         {
+/* turn this off too- bg pixmap is controlled by avoid damage directly
+            ee->engine.x.using_bg_pixmap = 0;
+            ecore_x_window_pixmap_set(ee->prop.window, 0);
+            ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
+ */
+         }
+     }
+}
+#else
+EAPI void
+ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee __UNUSED__, int on __UNUSED__)
+{
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+EAPI int
+ecore_evas_software_x11_direct_resize_get(const Ecore_Evas *ee)
+{
+   return ee->engine.x.direct_resize;
+}
+#else
+EAPI int
+ecore_evas_software_x11_direct_resize_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
+EAPI void
+ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
+{
+   Ecore_X_Window *winp;
+
+   winp = malloc(sizeof(Ecore_X_Window));
+   if (winp)
+     {
+       *winp = win;
+       ee->engine.x.win_extra = eina_list_append(ee->engine.x.win_extra, winp);
+        ecore_x_input_multi_select(win);
+       ecore_event_window_register(win, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+     }
+}
+#else
+EAPI void
+ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee __UNUSED__, Ecore_X_Window win __UNUSED__)
+{
+}
+#endif
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI Ecore_Evas *
+ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent,
+                     int x, int y, int w, int h)
+{
+   return ecore_evas_gl_x11_options_new(disp_name, parent, x, y, w, h, NULL);
+}
+EAPI Ecore_Evas *
+ecore_evas_gl_x11_options_new(const char *disp_name, Ecore_X_Window parent,
+                              int x, int y, int w, int h, const int *opt)
+{
+# ifdef HAVE_ECORE_X_XCB
+   Ecore_Evas *ee = NULL;
+# else
+   Ecore_Evas *ee;
+   int rmethod;
+
+   rmethod = evas_render_method_lookup("gl_x11");
+   if (!rmethod) return NULL;
+   if (!ecore_x_init(disp_name)) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_x_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
+
+   ee->driver = "opengl_x11";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = w;
+   ee->h = h;
+   ee->req.x = ee->x;
+   ee->req.y = ee->y;
+   ee->req.w = ee->w;
+   ee->req.h = ee->h;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   ee->engine.x.state.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, _ecore_evas_x_flush_pre, ee);
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _ecore_evas_x_flush_post, ee);
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   if (parent == 0) parent = DefaultRootWindow(ecore_x_display_get());
+   ee->engine.x.win_root = parent;
+
+   if (ee->engine.x.win_root != 0)
+     {
+        ee->engine.x.screen_num = 1; /* FIXME: get real scren # */
+       /* FIXME: round trip in ecore_x_window_argb_get */
+       if (ecore_x_window_argb_get(ee->engine.x.win_root))
+         {
+             ee->prop.window = _ecore_evas_x_gl_window_new
+               (ee, ee->engine.x.win_root, x, y, w, h, 0, 1, opt);
+         }
+       else
+          ee->prop.window = _ecore_evas_x_gl_window_new
+          (ee, ee->engine.x.win_root, x, y, w, h, 0, 0, opt);
+     }
+   else
+     ee->prop.window = _ecore_evas_x_gl_window_new
+     (ee, ee->engine.x.win_root, x, y, w, h, 0, 0, opt);
+   if (!ee->prop.window)
+     {
+        ecore_evas_free(ee);
+        return NULL;
+     }
+   if (getenv("DESKTOP_STARTUP_ID"))
+     {
+       ecore_x_netwm_startup_id_set(ee->prop.window,
+                                    getenv("DESKTOP_STARTUP_ID"));
+       /* NB: on linux this may simply empty the env as opposed to completely
+        * unset it to being empty - unsure as solartis libc crashes looking
+        * for the '=' char */
+//     putenv((char*)"DESKTOP_STARTUP_ID=");
+     }
+
+   ecore_x_icccm_hints_set(ee->prop.window,
+                           1 /* accepts_focus */,
+                           ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                           0 /* icon_pixmap */,
+                           0 /* icon_mask */,
+                           0 /* icon_window */,
+                           0 /* window_group */,
+                           0 /* is_urgent */);
+   
+   ee->engine.func->fn_render = _ecore_evas_x_render;
+   _ecore_evas_register(ee);
+   ecore_x_input_multi_select(ee->prop.window);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+# endif /* HAVE_ECORE_X_XCB */
+
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_gl_x11_new(const char *disp_name __UNUSED__, Ecore_X_Window parent __UNUSED__,
+                     int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+EAPI Ecore_Evas *
+ecore_evas_gl_x11_options_new(const char *disp_name, Ecore_X_Window parent,
+                              int x, int y, int w, int h, const int *opt)
+{
+   return NULL;
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI Ecore_X_Window
+ecore_evas_gl_x11_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_X_Window) ecore_evas_window_get(ee);
+}
+#else
+EAPI Ecore_X_Window
+ecore_evas_gl_x11_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI void
+ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, int on)
+{
+   ee->engine.x.direct_resize = on;
+}
+#else
+EAPI void
+ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee __UNUSED__, int on __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI int
+ecore_evas_gl_x11_direct_resize_get(const Ecore_Evas *ee)
+{
+   return ee->engine.x.direct_resize;
+}
+#else
+EAPI int
+ecore_evas_gl_x11_direct_resize_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI void
+ecore_evas_gl_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
+{
+   ecore_evas_software_x11_extra_event_window_add(ee, win);
+}
+#else
+EAPI void
+ecore_evas_gl_x11_extra_event_window_add(Ecore_Evas *ee __UNUSED__, Ecore_X_Window win __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#ifdef BUILD_ECORE_EVAS_OPENGL_X11
+EAPI void
+ecore_evas_gl_x11_pre_post_swap_callback_set(const Ecore_Evas *ee, void *data, void (*pre_cb) (void *data, Evas *e), void (*post_cb) (void *data, Evas *e))
+{
+   Evas_Engine_Info_GL_X11 *einfo;
+   
+   if (!(!strcmp(ee->driver, "opengl_x11"))) return;
+   einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+        einfo->callback.pre_swap = pre_cb;
+        einfo->callback.pre_swap = post_cb;
+        einfo->callback.data = data;
+       if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+          }
+     }
+}
+#else
+EAPI void
+ecore_evas_gl_x11_pre_post_swap_callback_set(const Ecore_Evas *ee, void *data, void (*pre_cb) (void *data, Evas *e), void (*post_cb) (void *data, Evas *e))
+{
+   return;
+}
+#endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+EAPI Ecore_Evas *
+ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent,
+                     int x, int y, int w, int h)
+{
+   Evas_Engine_Info_XRender_X11 *einfo;
+   Ecore_Evas *ee;
+   int rmethod;
+
+   rmethod = evas_render_method_lookup("xrender_x11");
+   if (!rmethod) return NULL;
+   if (!ecore_x_init(disp_name)) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_x_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
+
+   ee->driver = "xrender_x11";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = w;
+   ee->h = h;
+   ee->req.x = ee->x;
+   ee->req.y = ee->y;
+   ee->req.w = ee->w;
+   ee->req.h = ee->h;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   ee->engine.x.state.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, _ecore_evas_x_flush_pre, ee);
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _ecore_evas_x_flush_post, ee);
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   ee->engine.x.win_root = parent;
+   ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
+   if (getenv("DESKTOP_STARTUP_ID"))
+     {
+       ecore_x_netwm_startup_id_set(ee->prop.window,
+                                    getenv("DESKTOP_STARTUP_ID"));
+       /* NB: on linux this may simply empty the env as opposed to completely
+        * unset it to being empty - unsure as solartis libc crashes looking
+        * for the '=' char */
+//     putenv((char*)"DESKTOP_STARTUP_ID=");
+     }
+   einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas);
+   if (einfo)
+     {
+# ifdef BUILD_ECORE_EVAS_XRENDER_XCB
+        xcb_screen_iterator_t iter;
+       xcb_screen_t         *screen;
+
+       /* FIXME: this is inefficient as its a round trip */
+       screen = ecore_x_default_screen_get();
+        iter = xcb_setup_roots_iterator (xcb_get_setup (ecore_x_connection_get()));
+       if (iter.rem > 1)
+         {
+             xcb_get_geometry_cookie_t cookie;
+             xcb_get_geometry_reply_t *reply;
+            Ecore_X_Window           *roots;
+            int                       num;
+            uint8_t                   i;
+
+            num = 0;
+             cookie = xcb_get_geometry_unchecked(ecore_x_connection_get(), parent);
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                  reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL);
+
+                 if (reply)
+                   {
+                      for (i = 0; i < num; xcb_screen_next (&iter), i++)
+                        {
+                           if (reply->root == roots[i])
+                             {
+                                screen = iter.data;
+                                break;
+                             }
+                        }
+                       free(reply);
+                   }
+                 free(roots);
+              }
+             else
+               {
+                  reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL);
+                  if (reply) free(reply);
+               }
+         }
+       einfo->info.backend = EVAS_ENGINE_INFO_XRENDER_BACKEND_XCB;
+       einfo->info.connection = ecore_x_connection_get();
+       einfo->info.screen = screen;
+       einfo->info.visual = screen->root_visual;
+# elif BUILD_ECORE_EVAS_XRENDER_X11
+       int screen;
+
+       /* FIXME: this is inefficient as its a round trip */
+       screen = DefaultScreen(ecore_x_display_get());
+       if (ScreenCount(ecore_x_display_get()) > 1)
+         {
+            Ecore_X_Window *roots;
+            int num, i;
+
+            num = 0;
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                 XWindowAttributes at;
+
+                 if (XGetWindowAttributes(ecore_x_display_get(),
+                                          parent, &at))
+                   {
+                      for (i = 0; i < num; i++)
+                        {
+                           if (at.root == roots[i])
+                             {
+                                screen = i;
+                                break;
+                             }
+                        }
+                   }
+                 free(roots);
+              }
+         }
+       einfo->info.backend = EVAS_ENGINE_INFO_XRENDER_BACKEND_XLIB;
+       einfo->info.connection = ecore_x_display_get();
+       einfo->info.screen = NULL;
+       einfo->info.visual = DefaultVisual(ecore_x_display_get(), screen);
+# endif /* BUILD_ECORE_EVAS_XRENDER_(XCB|X11) */
+       einfo->info.drawable = ee->prop.window;
+       if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             WRN("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+             ecore_evas_free(ee);
+             return NULL;
+          }
+     }
+
+   ecore_x_icccm_hints_set(ee->prop.window,
+                           1 /* accepts_focus */,
+                           ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                           0 /* icon_pixmap */,
+                           0 /* icon_mask */,
+                           0 /* icon_window */,
+                           0 /* window_group */,
+                           0 /* is_urgent */);
+   
+   ee->engine.func->fn_render = _ecore_evas_x_render;
+   _ecore_evas_register(ee);
+   ecore_x_input_multi_select(ee->prop.window);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_xrender_x11_new(const char *disp_name __UNUSED__, Ecore_X_Window parent __UNUSED__,
+                           int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+#endif /* ! BUILD_ECORE_EVAS_XRENDER_X11 && ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+EAPI Ecore_X_Window
+ecore_evas_xrender_x11_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_X_Window) ecore_evas_window_get(ee);
+}
+#else
+EAPI Ecore_X_Window
+ecore_evas_xrender_x11_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_XRENDER_X11 && ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+EAPI void
+ecore_evas_xrender_x11_direct_resize_set(Ecore_Evas *ee, int on)
+{
+   ee->engine.x.direct_resize = on;
+}
+#else
+EAPI void
+ecore_evas_xrender_x11_direct_resize_set(Ecore_Evas *ee __UNUSED__, int on __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_XRENDER_X11 && ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+EAPI int
+ecore_evas_xrender_x11_direct_resize_get(const Ecore_Evas *ee)
+{
+   return ee->engine.x.direct_resize;
+}
+#else
+EAPI int
+ecore_evas_xrender_x11_direct_resize_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_XRENDER_X11 && ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if defined (BUILD_ECORE_EVAS_XRENDER_X11) || defined (BUILD_ECORE_EVAS_XRENDER_XCB)
+EAPI void
+ecore_evas_xrender_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
+{
+   ecore_evas_software_x11_extra_event_window_add(ee, win);
+}
+#else
+EAPI void
+ecore_evas_xrender_x11_extra_event_window_add(Ecore_Evas *ee __UNUSED__, Ecore_X_Window win __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_XRENDER_X11 && ! BUILD_ECORE_EVAS_XRENDER_XCB */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+EAPI Ecore_Evas *
+ecore_evas_software_x11_16_new(const char *disp_name, Ecore_X_Window parent,
+                               int x, int y, int w, int h)
+{
+   Evas_Engine_Info_Software_16_X11 *einfo;
+   Ecore_Evas *ee;
+   int rmethod;
+   static int redraw_debug = -1;
+
+   rmethod = evas_render_method_lookup("software_16_x11");
+   if (!rmethod) return NULL;
+   if (!ecore_x_init(disp_name)) return NULL;
+   ee = calloc(1, sizeof(Ecore_Evas));
+   if (!ee) return NULL;
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   _ecore_evas_x_init();
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
+
+   ee->driver = "software_16_x11";
+   if (disp_name) ee->name = strdup(disp_name);
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->x = x;
+   ee->y = y;
+   ee->w = w;
+   ee->h = h;
+   ee->req.x = ee->x;
+   ee->req.y = ee->y;
+   ee->req.w = ee->w;
+   ee->req.h = ee->h;
+
+   ee->prop.max.w = 32767;
+   ee->prop.max.h = 32767;
+   ee->prop.layer = 4;
+   ee->prop.request_pos = 0;
+   ee->prop.sticky = 0;
+   ee->engine.x.state.sticky = 0;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, _ecore_evas_x_flush_pre, ee);
+   evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _ecore_evas_x_flush_post, ee);
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   ee->engine.x.win_root = parent;
+   if (parent != 0)
+     {
+       /* FIXME: round trip in ecore_x_window_argb_get */
+       if (ecore_x_window_argb_get(parent))
+         {
+            ee->prop.window = ecore_x_window_argb_new(parent, x, y, w, h);
+         }
+       else
+         ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
+     }
+   else
+     ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
+   if (getenv("DESKTOP_STARTUP_ID"))
+     {
+       ecore_x_netwm_startup_id_set(ee->prop.window,
+                                    getenv("DESKTOP_STARTUP_ID"));
+       /* NB: on linux this may simply empty the env as opposed to completely
+        * unset it to being empty - unsure as solartis libc crashes looking
+        * for the '=' char */
+//     putenv((char*)"DESKTOP_STARTUP_ID=");
+     }
+   einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
+
+   if (einfo)
+     {
+       if (ScreenCount(ecore_x_display_get()) > 1)
+         {
+            Ecore_X_Window *roots;
+            int num, i;
+
+            num = 0;
+            roots = ecore_x_window_root_list(&num);
+            if (roots)
+              {
+                 XWindowAttributes at;
+
+                 if (XGetWindowAttributes(ecore_x_display_get(),
+                                          parent, &at))
+                   {
+                      for (i = 0; i < num; i++)
+                        {
+                           if (at.root == roots[i])
+                             break;
+                        }
+                   }
+                 free(roots);
+              }
+         }
+
+       if (redraw_debug < 0)
+         {
+            if (getenv("REDRAW_DEBUG"))
+              redraw_debug = atoi(getenv("REDRAW_DEBUG"));
+            else
+              redraw_debug = 0;
+         }
+       einfo->info.display  = ecore_x_display_get();
+       einfo->info.drawable = ee->prop.window;
+
+       if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+          {
+             WRN("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+             ecore_evas_free(ee);
+             return NULL;
+          }
+     }
+
+   ecore_x_icccm_hints_set(ee->prop.window,
+                           1 /* accepts_focus */,
+                           ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */,
+                           0 /* icon_pixmap */,
+                           0 /* icon_mask */,
+                           0 /* icon_window */,
+                           0 /* window_group */,
+                           0 /* is_urgent */);
+   
+   ee->engine.func->fn_render = _ecore_evas_x_render;
+   _ecore_evas_register(ee);
+   ecore_x_input_multi_select(ee->prop.window);
+   ecore_event_window_register(ee->prop.window, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+   return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_software_x11_16_new(const char *disp_name __UNUSED__, Ecore_X_Window parent __UNUSED__,
+                               int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   return NULL;
+}
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+EAPI Ecore_X_Window
+ecore_evas_software_x11_16_window_get(const Ecore_Evas *ee)
+{
+   return (Ecore_X_Window) ecore_evas_window_get(ee);
+}
+#else
+EAPI Ecore_X_Window
+ecore_evas_software_x11_16_window_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+EAPI void
+ecore_evas_software_x11_16_direct_resize_set(Ecore_Evas *ee, int on)
+{
+   ee->engine.x.direct_resize = on;
+   if (ee->prop.avoid_damage)
+     {
+       if (ee->engine.x.direct_resize)
+         {
+/* turn this off for now
+            ee->engine.x.using_bg_pixmap = 1;
+            ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
+ */
+         }
+       else
+         {
+/* turn this off too- bg pixmap is controlled by avoid damage directly
+            ee->engine.x.using_bg_pixmap = 0;
+            ecore_x_window_pixmap_set(ee->prop.window, 0);
+            ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
+ */
+         }
+     }
+}
+#else
+EAPI void
+ecore_evas_software_x11_16_direct_resize_set(Ecore_Evas *ee __UNUSED__, int on __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+EAPI int
+ecore_evas_software_x11_16_direct_resize_get(const Ecore_Evas *ee)
+{
+   return ee->engine.x.direct_resize;
+}
+#else
+EAPI int
+ecore_evas_software_x11_16_direct_resize_get(const Ecore_Evas *ee __UNUSED__)
+{
+   return 0;
+}
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+#if BUILD_ECORE_EVAS_SOFTWARE_16_X11
+EAPI void
+ecore_evas_software_x11_16_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
+{
+   Ecore_X_Window *winp;
+
+   winp = malloc(sizeof(Ecore_X_Window));
+   if (winp)
+     {
+       *winp = win;
+       ee->engine.x.win_extra = eina_list_append(ee->engine.x.win_extra, winp);
+        ecore_x_input_multi_select(win);
+       ecore_event_window_register(win, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
+     }
+}
+#else
+EAPI void
+ecore_evas_software_x11_16_extra_event_window_add(Ecore_Evas *ee __UNUSED__, Ecore_X_Window win __UNUSED__)
+{
+}
+#endif /* ! BUILD_ECORE_EVAS_SOFTWARE_16_X11 */
diff --git a/src/lib/ecore_fb/.cvsignore b/src/lib/ecore_fb/.cvsignore
new file mode 100644 (file)
index 0000000..6ff5cc5
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_fb.la
diff --git a/src/lib/ecore_fb/Ecore_Fb.h b/src/lib/ecore_fb/Ecore_Fb.h
new file mode 100644 (file)
index 0000000..5374817
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef _ECORE_FB_H
+#define _ECORE_FB_H
+
+#ifdef EAPI
+#undef EAPI
+#endif
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+/**
+ * @file
+ * @brief Ecore frame buffer system functions.
+ */
+
+/* FIXME:
+ * maybe a new module?
+ * - code to get battery info
+ * - code to get thermal info
+ * ecore evas fb isnt good enough for weird things, like multiple fb's, same happens here.
+ * backlight support using new kernel interface
+ * absolute axis
+ * joystick
+ * ecore_fb_li_device_close_all ? or a shutdown of the subsystem?
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Ecore_Fb_Input_Device Ecore_Fb_Input_Device; /* an input device handler */
+
+/* device capabilities */
+enum _Ecore_Fb_Input_Device_Cap
+{
+   ECORE_FB_INPUT_DEVICE_CAP_NONE            = 0x00000000,
+     ECORE_FB_INPUT_DEVICE_CAP_RELATIVE        = 0x00000001,
+     ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE        = 0x00000002,
+     ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS = 0x00000004
+};
+typedef enum   _Ecore_Fb_Input_Device_Cap Ecore_Fb_Input_Device_Cap;
+
+EAPI extern int ECORE_FB_EVENT_KEY_DOWN; /**< FB Key Down event */
+EAPI extern int ECORE_FB_EVENT_KEY_UP; /**< FB Key Up event */
+EAPI extern int ECORE_FB_EVENT_MOUSE_BUTTON_DOWN; /**< FB Mouse Down event */
+EAPI extern int ECORE_FB_EVENT_MOUSE_BUTTON_UP; /**< FB Mouse Up event */
+EAPI extern int ECORE_FB_EVENT_MOUSE_MOVE; /**< FB Mouse Move event */
+EAPI extern int ECORE_FB_EVENT_MOUSE_WHEEL; /**< FB Mouse Wheel event */
+
+typedef struct _Ecore_Fb_Event_Key_Down          Ecore_Fb_Event_Key_Down; /**< FB Key Down event */
+typedef struct _Ecore_Fb_Event_Key_Up            Ecore_Fb_Event_Key_Up; /**< FB Key Up event */
+typedef struct _Ecore_Fb_Event_Mouse_Button_Down Ecore_Fb_Event_Mouse_Button_Down; /**< FB Mouse Down event */
+typedef struct _Ecore_Fb_Event_Mouse_Button_Up   Ecore_Fb_Event_Mouse_Button_Up; /**< FB Mouse Up event */
+typedef struct _Ecore_Fb_Event_Mouse_Move        Ecore_Fb_Event_Mouse_Move; /**< FB Mouse Move event */
+typedef struct _Ecore_Fb_Event_Mouse_Wheel       Ecore_Fb_Event_Mouse_Wheel; /**< FB Mouse Wheel event */
+
+struct _Ecore_Fb_Event_Key_Down /** FB Key Down event */
+{
+   Ecore_Fb_Input_Device *dev; /**< The device associated with the event */
+   char   *keyname; /**< The name of the key that was pressed */
+   char   *keysymbol; /**< The logical symbol of the key that was pressed */
+   char   *key_compose; /**< The UTF-8 string conversion if any */
+};
+   
+struct _Ecore_Fb_Event_Key_Up /** FB Key Up event */
+{
+   Ecore_Fb_Input_Device *dev; /**< The device associated with the event */
+   char   *keyname; /**< The name of the key that was released */
+   char   *keysymbol; /**< The logical symbol of the key that was pressed */
+   char   *key_compose; /**< The UTF-8 string conversion if any */
+};
+   
+struct _Ecore_Fb_Event_Mouse_Button_Down /** FB Mouse Down event */
+{
+   Ecore_Fb_Input_Device *dev; /**< The device associated with the event */
+   int     button; /**< Mouse button that was pressed (1 - 32) */
+   int     x; /**< Mouse co-ordinates when mouse button was pressed */
+   int     y; /**< Mouse co-ordinates when mouse button was pressed */
+   int     double_click : 1; /**< Set if click was a double click */
+   int     triple_click : 1; /**< Set if click was a triple click  */
+};
+   
+struct _Ecore_Fb_Event_Mouse_Button_Up /** FB Mouse Up event */
+{
+   Ecore_Fb_Input_Device *dev; /**< The device associated with the event */
+   int     button; /**< Mouse button that was released (1 - 32) */
+   int     x; /**< Mouse co-ordinates when mouse button was raised */
+   int     y; /**< Mouse co-ordinates when mouse button was raised */
+};
+   
+struct _Ecore_Fb_Event_Mouse_Move /** FB Mouse Move event */ 
+{
+   Ecore_Fb_Input_Device *dev; /**< The device associated with the event */
+   int     x; /**< Mouse co-ordinates where the mouse cursor moved to */
+   int     y; /**< Mouse co-ordinates where the mouse cursor moved to */
+};
+   
+struct _Ecore_Fb_Event_Mouse_Wheel /** FB Mouse Wheel event */
+{
+   Ecore_Fb_Input_Device *dev;
+   int x,y;
+   int direction; /* 0 = vertical, 1 = horizontal */
+   int wheel; /* value 1 (left/up), -1 (right/down) */
+};
+
+/* ecore_fb_vt.c */
+EAPI void ecore_fb_callback_gain_set(void (*func) (void *data), void *data);
+EAPI void ecore_fb_callback_lose_set(void (*func) (void *data), void *data);
+/* ecore_fb_li.c */
+EAPI Ecore_Fb_Input_Device           *ecore_fb_input_device_open(const char *dev);
+EAPI void                             ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev);
+EAPI void                             ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, int listen);
+EAPI const char                      *ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev);
+EAPI Ecore_Fb_Input_Device_Cap        ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev);
+EAPI void                             ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h);
+EAPI void                             ecore_fb_input_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold);
+EAPI double                           ecore_fb_input_threshold_click_get(Ecore_Fb_Input_Device *dev);
+/* ecore_fb.c */
+EAPI int    ecore_fb_init(const char *name);
+EAPI int    ecore_fb_shutdown(void);
+EAPI void   ecore_fb_size_get(int *w, int *h);   
+
+EAPI void   ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap);
+EAPI void   ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap);
+   
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_fb/Makefile.am b/src/lib/ecore_fb/Makefile.am
new file mode 100644 (file)
index 0000000..2d82071
--- /dev/null
@@ -0,0 +1,35 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore \
+@TSLIB_CFLAGS@ \
+@EINA_CFLAGS@
+
+if BUILD_ECORE_FB
+
+lib_LTLIBRARIES = libecore_fb.la
+include_HEADERS = \
+Ecore_Fb.h
+
+libecore_fb_la_SOURCES = \
+ecore_fb.c \
+ecore_fb_vt.c \
+ecore_fb_li.c \
+ecore_fb_ts.c
+# deprecated sources (might not compile):
+# ecore_fb_kbd.c
+# ecore_fb_ps2.c
+
+libecore_fb_la_LIBADD = \
+@TSLIB_LIBS@ \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EINA_LIBS@
+
+libecore_fb_la_LDFLAGS = -version-info @version_info@ @ecore_fb_release_info@
+
+endif
+
+EXTRA_DIST = \
+ecore_fb_private.h \
+ecore_fb_keytable.h
diff --git a/src/lib/ecore_fb/ecore_fb.c b/src/lib/ecore_fb/ecore_fb.c
new file mode 100644 (file)
index 0000000..acc380a
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore_Fb.h"
+#include "ecore_fb_private.h"
+
+static void _ecore_fb_size_get(int *w, int *h);
+
+EAPI int ECORE_FB_EVENT_KEY_DOWN = 0;
+EAPI int ECORE_FB_EVENT_KEY_UP = 0;
+EAPI int ECORE_FB_EVENT_MOUSE_BUTTON_DOWN = 0;
+EAPI int ECORE_FB_EVENT_MOUSE_BUTTON_UP = 0;
+EAPI int ECORE_FB_EVENT_MOUSE_MOVE = 0;
+EAPI int ECORE_FB_EVENT_MOUSE_WHEEL = 0;
+
+static int _ecore_fb_init_count = 0;
+static int _ecore_fb_console_w = 0;
+static int _ecore_fb_console_h = 0;
+
+static double _ecore_fb_double_click_time = 0.25;
+
+
+/**
+ * @defgroup Ecore_FB_Library_Group Framebuffer Library Functions
+ *
+ * Functions used to set up and shut down the Ecore_Framebuffer functions.
+ */
+
+/**
+ * Sets up the Ecore_Fb library.
+ * @param   name device target name
+ * @return  @c 0 on failure.  Otherwise, the number of times the library has
+ *          been initialised without being shut down.
+ * @ingroup Ecore_FB_Library_Group
+ */
+EAPI int
+ecore_fb_init(const char *name __UNUSED__)
+{
+   if (++_ecore_fb_init_count != 1)
+     return _ecore_fb_init_count;
+
+   if (!ecore_fb_vt_init())
+     return --_ecore_fb_init_count;
+
+   ECORE_FB_EVENT_KEY_DOWN          = ecore_event_type_new();
+   ECORE_FB_EVENT_KEY_UP            = ecore_event_type_new();
+   ECORE_FB_EVENT_MOUSE_BUTTON_DOWN = ecore_event_type_new();
+   ECORE_FB_EVENT_MOUSE_BUTTON_UP   = ecore_event_type_new();
+   ECORE_FB_EVENT_MOUSE_MOVE        = ecore_event_type_new();
+   ECORE_FB_EVENT_MOUSE_WHEEL       = ecore_event_type_new();
+   _ecore_fb_size_get(&_ecore_fb_console_w, &_ecore_fb_console_h);
+
+   return _ecore_fb_init_count;
+}
+
+/**
+ * Shuts down the Ecore_Fb library. 
+ * @return  @c The number of times the system has been initialised without
+ *             being shut down.
+ * @ingroup Ecore_FB_Library_Group
+ */
+EAPI int
+ecore_fb_shutdown(void)
+{    
+   if (--_ecore_fb_init_count != 0)
+     return _ecore_fb_init_count;
+
+   ecore_fb_vt_shutdown();
+
+   return _ecore_fb_init_count;
+}
+
+
+/**
+ * Retrieves the width and height of the current frame buffer in pixels.
+ * @param w Pointer to an integer in which to store the width.
+ * @param h Pointer to an interge in which to store the height.
+ */
+EAPI void
+ecore_fb_size_get(int *w, int *h)
+{
+   if (w) *w = _ecore_fb_console_w;
+   if (h) *h = _ecore_fb_console_h;
+}
+
+static void
+_ecore_fb_size_get(int *w, int *h)
+{
+   struct fb_var_screeninfo fb_var;
+   int fb;
+   
+   fb = open("/dev/fb0", O_RDWR);
+   if (fb < 0)
+     {
+       if (w) *w = 0;
+       if (h) *h = 0;
+       return;
+     }
+   if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1)
+     {
+       if (w) *w = 0;
+       if (h) *h = 0;
+       return;
+     }
+   close(fb);
+   if (w) *w = fb_var.xres;
+   if (h) *h = fb_var.yres;
+}
diff --git a/src/lib/ecore_fb/ecore_fb_kbd.c b/src/lib/ecore_fb/ecore_fb_kbd.c
new file mode 100644 (file)
index 0000000..0cc1186
--- /dev/null
@@ -0,0 +1,305 @@
+static void _ecore_fb_event_free_key_down(void *data, void *ev);
+static void _ecore_fb_event_free_key_up(void *data, void *ev);
+
+static const char *_ecore_fb_kbd_syms[128 * 6] =
+{
+#include "ecore_fb_keytable.h"
+};
+
+static const char *_ecore_fb_btn_syms[128] =
+{
+   "0x00",
+     "Escape", 
+     "F1", 
+     "F2", 
+     "F3", 
+     "F4", 
+     "Up", 
+     "Right",
+     "Left", 
+     "Down", 
+     "Return", 
+     "0x1b", 
+     "0x1c", 
+     "0x1d", 
+     "0x1e",
+     "0x1f",
+     "0x20", 
+     "0x21", 
+     "0x22", 
+     "0x23", 
+     "0x24", 
+     "0x25", 
+     "0x26", 
+     "0x27",
+     "0x28", 
+     "0x29", 
+     "0x2a",
+     "0x2b",
+     "0x2c",
+     "0x2d",
+     "0x2e", 
+     "0x2f", 
+     "0x30", 
+     "0x31", 
+     "0x32", 
+     "0x33", 
+     "0x34", 
+     "0x35", 
+     "0x36", 
+     "0x37",
+     "0x38", 
+     "0x39", 
+     "0x3a",
+     "0x3b",
+     "0x3c",
+     "0x3d",
+     "0x3e", 
+     "0x3f", 
+     "0x40", 
+     "0x41", 
+     "0x42", 
+     "0x43", 
+     "0x44", 
+     "0x45", 
+     "0x46", 
+     "0x47",
+     "0x48", 
+     "0x49", 
+     "0x4a",
+     "0x4b",
+     "0x4c",
+     "0x4d",
+     "0x4e", 
+     "0x4f", 
+     "0x50", 
+     "0x51", 
+     "0x52", 
+     "0x53", 
+     "0x54", 
+     "0x55", 
+     "0x56", 
+     "0x57",
+     "0x58", 
+     "0x59", 
+     "0x5a",
+     "0x5b",
+     "0x5c",
+     "0x5d",
+     "0x5e", 
+     "0x5f", 
+     "0x60", 
+     "0x61", 
+     "0x62", 
+     "0x63", 
+     "0x64", 
+     "0x65", 
+     "0x66", 
+     "0x67",
+     "0x68", 
+     "0x69", 
+     "0x6a",
+     "0x6b",
+     "0x6c",
+     "0x6d",
+     "0x6e", 
+     "0x6f", 
+     "0x70", 
+     "0x71", 
+     "0x72", 
+     "0x73", 
+     "0x74", 
+     "0x75", 
+     "0x76", 
+     "0x77",
+     "0x78", 
+     "0x79", 
+     "0x7a",
+     "0x7b",
+     "0x7c",
+     "0x7d",
+     "0x7e", 
+     "0x7f"
+};
+static int _ecore_fb_kbd_fd = 0;
+static int _ecore_fb_ctrl = 0;
+static int _ecore_fb_alt = 0;
+static int _ecore_fb_shift = 0;
+static int _ecore_fb_lock = 0;
+
+static Ecore_Fd_Handler *_ecore_fb_kbd_fd_handler_handle = NULL;
+static int _ecore_fb_kbd_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
+static void 
+_ecore_fb_event_free_key_down(void *data __UNUSED__, void *ev)
+{
+   Ecore_Fb_Event_Key_Up *e;
+   e = ev;
+   free(e->keyname);
+   if (e->keysymbol) free(e->keysymbol);
+   if (e->key_compose) free(e->key_compose);
+   free(e);
+}
+
+static void
+_ecore_fb_event_free_key_up(void *data __UNUSED__, void *ev)
+{
+   Ecore_Fb_Event_Key_Up *e;
+   
+   e = ev;
+   free(e->keyname);
+   if (e->keysymbol) free(e->keysymbol);
+   if (e->key_compose) free(e->key_compose);
+   free(e);
+}
+
+static int
+_ecore_fb_kbd_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   int v = 0;
+   
+   do
+     {
+       unsigned char buf;
+       
+       v = read(_ecore_fb_kbd_fd, &buf, 1);
+       if (v < 0) return 1;
+       if (v < 1) return 1;
+       if (!(buf & 0x80))
+         {
+            /* DOWN */
+            int vt_switch = -1;
+            Ecore_Fb_Event_Key_Down *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Key_Down));
+            if (!e) goto retry;
+            if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd)
+              {
+                 int add = 0;
+                 
+                 if (_ecore_fb_shift) add = 1;
+                 else if (_ecore_fb_lock) add = 2;
+                 e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 6]);
+                 e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + add]);
+                 e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + 3 + add]);
+              }
+            else
+              e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]);
+            if (!e->keyname)
+              {
+                 free(e);
+                 goto retry;
+              }
+            ecore_event_add(ECORE_FB_EVENT_KEY_DOWN, e, _ecore_fb_event_free_key_down, NULL);
+            if (!strcmp(e->keyname, "Control_L"))
+              _ecore_fb_ctrl++;
+            else if (!strcmp(e->keyname, "Control_R"))
+              _ecore_fb_ctrl++;
+            else if (!strcmp(e->keyname, "Alt_L"))
+              _ecore_fb_alt++;
+            else if (!strcmp(e->keyname, "Alt_R"))
+              _ecore_fb_alt++;
+            else if (!strcmp(e->keyname, "Shift_L"))
+              _ecore_fb_shift++;
+            else if (!strcmp(e->keyname, "Shift_R"))
+              _ecore_fb_shift++;
+            else if (!strcmp(e->keyname, "Caps_Lock"))
+              _ecore_fb_lock++;
+            else if (!strcmp(e->keyname, "F1")) vt_switch = 0;
+            else if (!strcmp(e->keyname, "F2")) vt_switch = 1;
+            else if (!strcmp(e->keyname, "F3")) vt_switch = 2;
+            else if (!strcmp(e->keyname, "F4")) vt_switch = 3;
+            else if (!strcmp(e->keyname, "F5")) vt_switch = 4;
+            else if (!strcmp(e->keyname, "F6")) vt_switch = 5;
+            else if (!strcmp(e->keyname, "F7")) vt_switch = 6;
+            else if (!strcmp(e->keyname, "F8")) vt_switch = 7;
+            else if (!strcmp(e->keyname, "F9")) vt_switch = 8;
+            else if (!strcmp(e->keyname, "F10")) vt_switch = 9;
+            else if (!strcmp(e->keyname, "F11")) vt_switch = 10;
+            else if (!strcmp(e->keyname, "F12")) vt_switch = 11;
+            if (_ecore_fb_ctrl > 2) _ecore_fb_ctrl = 2;
+            if (_ecore_fb_alt > 2) _ecore_fb_alt = 2;
+            if ((vt_switch >= 0) &&
+                (_ecore_fb_ctrl) &&
+                (_ecore_fb_alt))
+              _ecore_fb_vt_switch(vt_switch);
+         }
+       else
+         {
+            /* UP */
+            Ecore_Fb_Event_Key_Up *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Key_Up));
+            if (!e) goto retry;
+            if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd)
+              {
+                 int add = 0;
+                 
+                 if (_ecore_fb_shift) add = 1;
+                 else if (_ecore_fb_lock) add = 2;
+                 e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 6]);
+                 e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + add]);
+                 e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + 3 + add]);
+              }
+            else
+              e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]);
+            if (!e->keyname)
+              {
+                 free(e);
+                 goto retry;
+              }
+            ecore_event_add(ECORE_FB_EVENT_KEY_UP, e, _ecore_fb_event_free_key_up, NULL);
+            if (!strcmp(e->keyname, "Control_L"))
+              _ecore_fb_ctrl--;
+            else if (!strcmp(e->keyname, "Control_R"))
+              _ecore_fb_ctrl--;
+            else if (!strcmp(e->keyname, "Alt_L"))
+              _ecore_fb_alt--;
+            else if (!strcmp(e->keyname, "Alt_R"))
+              _ecore_fb_alt--;
+            else if (!strcmp(e->keyname, "Shift_L"))
+              _ecore_fb_shift--;
+            else if (!strcmp(e->keyname, "Shift_R"))
+              _ecore_fb_shift--;
+            else if (!strcmp(e->keyname, "Caps_Lock"))
+              _ecore_fb_lock--;
+            if (_ecore_fb_ctrl < 0) _ecore_fb_ctrl = 0;
+            if (_ecore_fb_alt < 0) _ecore_fb_alt = 0;
+            if (_ecore_fb_shift < 0) _ecore_fb_shift = 0;
+            if (_ecore_fb_lock < 0) _ecore_fb_lock = 0;
+         }
+       retry:
+       ;
+     }
+   while (v > 0);
+   return 1;
+}
+
+int
+ecore_fb_kbd_init(void)
+{
+   int prev_flags;
+   
+   prev_flags = fcntl(_ecore_fb_kbd_fd, F_GETFL);
+   fcntl(_ecore_fb_kbd_fd, F_SETFL, prev_flags | O_NONBLOCK);
+   _ecore_fb_kbd_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_kbd_fd,
+                                                                   ECORE_FD_READ,
+                                                                   _ecore_fb_kbd_fd_handler, NULL,
+                                                                   NULL, NULL);
+   if(!_ecore_fb_kbd_fd_handler_handle) return 0;
+   return 1;
+}
+
+void
+ecore_fb_kbd_shutdown(void)
+{
+   if (_ecore_fb_kbd_fd >= 0) close(_ecore_fb_kbd_fd);
+   if (_ecore_fb_kbd_fd_handler_handle) 
+     ecore_main_fd_handler_del(_ecore_fb_kbd_fd_handler_handle);
+   _ecore_fb_kbd_fd = 0;
+   _ecore_fb_kbd_fd_handler_handle = NULL;
+   _ecore_fb_ctrl = 0;
+   _ecore_fb_lock = 0;
+   _ecore_fb_shift = 0;
+   _ecore_fb_alt = 0;
+}
diff --git a/src/lib/ecore_fb/ecore_fb_keytable.h b/src/lib/ecore_fb/ecore_fb_keytable.h
new file mode 100644 (file)
index 0000000..ff03497
--- /dev/null
@@ -0,0 +1,129 @@
+/* this table was taken from ecore_fb, is the default en layout */
+         "0x00",          "0x00",          "0x00", /**/"",    "",    "",/***/
+       "Escape",        "Escape",        "Escape", /**/"",    "",    "",/***/
+            "1",        "exclam",             "1", /**/"1",   "!",   "1",/***/
+            "2",            "at",             "2", /**/"2",   "@",   "2",/***/
+            "3",    "numbersign",             "3", /**/"3",   "#",   "3",/***/
+            "4",        "dollar",             "4", /**/"4",   "$",   "4",/***/
+            "5",       "percent",             "5", /**/"5",   "%",   "5",/***/
+            "6",  "asciicircumm",             "6", /**/"6",   "^",   "6",/***/
+            "7",     "ampersand",             "7", /**/"7",   "&",   "7",/***/
+            "8",       "asterik",             "8", /**/"8",   "*",   "8",/***/
+            "9",     "parenleft",             "9", /**/"9",   "(",   "9",/***/
+            "0",    "parenright",             "0", /**/"0",   ")",   "0",/***/
+        "minus",    "underscore",         "minus", /**/"-",   "_",   "-",/***/
+        "equal",          "plus",         "equal", /**/"=",   "+",   "=",/***/
+    "BackSpace",     "BackSpace",     "BackSpace", /**/"\010","\010","\010",/***/
+          "Tab",  "ISO_Left_Tab",           "Tab", /**/"\011","",    "\011",/***/
+            "q",             "Q",             "Q", /**/"q",   "Q",   "Q",/***/
+            "w",             "W",             "W", /**/"w",   "W",   "W",/***/
+            "e",             "E",             "E", /**/"e",   "E",   "E",/***/
+            "r",             "R",             "R", /**/"r",   "R",   "R",/***/
+            "t",             "T",             "T", /**/"t",   "T",   "T",/***/
+            "y",             "Y",             "Y", /**/"y",   "Y",   "Y",/***/
+            "u",             "U",             "U", /**/"u",   "U",   "U",/***/
+            "i",             "I",             "I", /**/"i",   "I",   "I",/***/
+            "o",             "O",             "O", /**/"o",   "O",   "O",/***/
+            "p",             "P",             "P", /**/"p",   "P",   "P",/***/
+  "bracketleft",     "braceleft",   "bracketleft", /**/"[",   "{",   "[",/***/
+ "bracketright",    "braceright",  "bracketright", /**/"]",   "}",   "]",/***/
+       "Return",        "Return",        "Return", /**/"\015","\015","\015",/***/
+    "Control_L",     "Control_L",     "Control_L", /**/"",    "",    "",/***/
+            "a",             "A",             "A", /**/"a",   "A",   "A",/***/
+            "s",             "S",             "S", /**/"s",   "S",   "S",/***/
+            "d",             "D",             "D", /**/"d",   "D",   "D",/***/
+            "f",             "F",             "F", /**/"f",   "F",   "F",/***/
+            "g",             "G",             "G", /**/"g",   "G",   "G",/***/
+            "h",             "h",             "H", /**/"h",   "H",   "H",/***/
+            "j",             "J",             "J", /**/"j",   "J",   "J",/***/
+            "k",             "K",             "K", /**/"k",   "K",   "K",/***/
+            "l",             "L",             "L", /**/"l",   "L",   "L",/***/
+    "semicolon",         "colon",     "semicolon", /**/";",   ":",   ";",/***/
+   "apostrophe",      "quotedbl",    "apostrophe", /**/"'",   "\"",  "'",/***/
+        "grave",    "asciitilde",         "grave", /**/"`",   "~",   "`",/***/
+      "Shift_L",       "Shift_L",       "Shift_L", /**/"",    "",    "",/***/
+    "backslash",           "bar",     "backslash", /**/"\\",  "|",   "\\",/***/
+            "z",             "Z",             "Z", /**/"z",   "Z",   "Z",/***/
+            "x",             "X",             "X", /**/"x",   "X",   "X",/***/
+            "c",             "C",             "C", /**/"c",   "C",   "C",/***/
+            "v",             "V",             "V", /**/"v",   "V",   "V",/***/
+            "b",             "B",             "B", /**/"b",   "B",   "B",/***/
+            "n",             "N",             "N", /**/"n",   "N",   "N",/***/
+            "m",             "M",             "M", /**/"m",   "M",   "M",/***/
+        "comma",          "less",         "comma", /**/",",   "<",   ",",/***/
+       "period",       "greater",        "period", /**/".",   ">",   ".",/***/
+        "slash",      "question",         "slash", /**/"/",   "?",   "/",/***/
+      "Shift_R",       "Shift_R",       "Shift_R", /**/"",    "",    "",/***/
+  "KP_Multiply",   "KP_Multiply",   "KP_Multiply", /**/"",    "*",   "",/***/
+        "Alt_L",         "Alt_L",         "Alt_L", /**/"",    "",    "",/***/
+        "space",         "space",         "space", /**/" ",   " ",   " ",/***/
+    "Caps_Lock",     "Caps_Lock",     "Caps_Lock", /**/"",    "",    "",/***/
+           "F1",            "F1",            "F1", /**/"",    "",    "",/***/
+           "F2",            "F2",            "F2", /**/"",    "",    "",/***/
+           "F3",            "F3",            "F3", /**/"",    "",    "",/***/
+           "F4",            "F4",            "F4", /**/"",    "",    "",/***/
+           "F5",            "F5",            "F5", /**/"",    "",    "",/***/
+           "F6",            "F6",            "F6", /**/"",    "",    "",/***/
+           "F7",            "F7",            "F7", /**/"",    "",    "",/***/
+           "F8",            "F8",            "F8", /**/"",    "",    "",/***/
+           "F9",            "F9",            "F9", /**/"",    "",    "",/***/
+          "F10",           "F10",           "F10", /**/"",    "",    "",/***/
+     "Num_Lock",      "Num_Lock",      "Num_Lock", /**/"",    "",    "",/***/
+  "Scroll_Lock",   "Scroll_Lock",   "Scroll_Lock", /**/"",    "",    "",/***/
+      "KP_Home",          "KP_7",       "KP_Home", /**/"",    "7",   "",/***/
+        "KP_Up",          "KP_8",         "KP_Up", /**/"",    "8",   "",/***/
+     "KP_Prior",          "KP_9",      "KP_Prior", /**/"",    "9",   "",/***/
+  "KP_Subtract",   "KP_Subtract",   "KP_Subtract", /**/"",    "",    "",/***/
+      "KP_Left",          "KP_4",       "KP_Left", /**/"",    "4",   "",/***/
+     "KP_Begin",          "KP_5",      "KP_Begin", /**/"",    "5",   "",/***/
+     "KP_Right",          "KP_6",      "KP_Right", /**/"",    "6",   "",/***/
+       "KP_Add",        "KP_Add",        "KP_Add", /**/"",    "",    "",/***/
+       "KP_End",          "KP_1",        "KP_End", /**/"",    "1",   "",/***/
+      "KP_Down",          "KP_2",       "KP_Down", /**/"",    "2",   "",/***/
+      "KP_Next",          "KP_3",       "KP_Next", /**/"",    "3",   "",/***/
+    "KP_Insert",          "KP_0",     "KP_Insert", /**/"",    "0",   "",/***/
+    "KP_Delete",    "KP_Decimal",     "KP_Delete", /**/"",    ".",   "",/***/
+        "0x54",          "0x54",          "0x54", /**/"",    "",    "",/***/
+         "0x55",          "0x55",          "0x55", /**/"",    "",    "",/***/
+         "0x56",          "0x56",          "0x56", /**/"",    "",    "",/***/
+          "F11",           "F11",           "F11", /**/"",    "",    "",/***/
+          "F12",           "F12",           "F12", /**/"",    "",    "",/***/
+         "0x59",          "0x59",          "0x59", /**/"",    "",    "",/***/
+         "0x5a",          "0x5a",          "0x5a", /**/"",    "",    "",/***/
+         "0x5b",          "0x5b",          "0x5b", /**/"",    "",    "",/***/
+         "0x5c",          "0x5c",          "0x5c", /**/"",    "",    "",/***/
+         "0x5d",          "0x5d",          "0x5d", /**/"",    "",    "",/***/
+         "0x5e",          "0x5e",          "0x5e", /**/"",    "",    "",/***/
+         "0x5f",          "0x5f",          "0x5f", /**/"",    "",    "",/***/
+     "KP_Enter",      "KP_Enter",      "KP_Enter", /**/"",    "",    "",/***/
+    "Control_R",     "Control_R",     "Control_R", /**/"",    "",    "",/***/
+    "KP_Divide",     "KP_Divide",     "KP_Divide", /**/"",    "",    "",/***/
+        "Print",         "Print",         "Print", /**/"",    "",    "",/***/
+        "Alt_R",         "Alt_R",         "Alt_R", /**/"",    "",    "",/***/
+         "0x65",          "0x65",          "0x65", /**/"",    "",    "",/***/
+         "Home",          "Home",          "Home", /**/"",    "",    "",/***/
+           "Up",            "Up",            "Up", /**/"",    "",    "",/***/
+        "Prior",         "Prior",         "Prior", /**/"",    "",    "",/***/
+         "Left",          "Left",          "Left", /**/"",    "",    "",/***/
+        "Right",         "Right",         "Right", /**/"",    "",    "",/***/
+          "End",           "End",           "End", /**/"",    "",    "",/***/
+         "Down",          "Down",          "Down", /**/"",    "",    "",/***/
+         "Next",          "Next",          "Next", /**/"",    "",    "",/***/
+       "Insert",        "Insert",        "Insert", /**/"",    "",    "",/***/
+       "Delete",        "Delete",        "Delete", /**/"\177","\177","\177",/***/
+         "0x70",          "0x70",          "0x70", /**/"",    "",    "",/***/
+         "0x71",          "0x71",          "0x71", /**/"",    "",    "",/***/
+         "0x72",          "0x72",          "0x72", /**/"",    "",    "",/***/
+         "0x73",          "0x73",          "0x73", /**/"",    "",    "",/***/
+         "0x74",          "0x74",          "0x74", /**/"",    "",    "",/***/
+         "0x75",          "0x75",          "0x75", /**/"",    "",    "",/***/
+         "0x76",          "0x76",          "0x76", /**/"",    "",    "",/***/
+        "Pause",         "Pause",         "Pause", /**/"",    "",    "",/***/
+         "0x78",          "0x78",          "0x78", /**/"",    "",    "",/***/
+         "0x79",          "0x79",          "0x79", /**/"",    "",    "",/***/
+         "0x7a",          "0x7a",          "0x7a", /**/"",    "",    "",/***/
+         "0x7b",          "0x7b",          "0x7b", /**/"",    "",    "",/***/
+         "0x7c",          "0x7c",          "0x7c", /**/"",    "",    "",/***/
+      "Super_L",       "Super_L",       "Super_L", /**/"",    "",    "",/***/
+      "Super_R",       "Super_R",       "Super_R", /**/"",    "",    "",/***/
+         "0x7f",          "0x7f",          "0x7f", /**/"",    "",    "" /***/
diff --git a/src/lib/ecore_fb/ecore_fb_li.c b/src/lib/ecore_fb/ecore_fb_li.c
new file mode 100644 (file)
index 0000000..c0e80eb
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore_Fb.h"
+#include "ecore_fb_private.h"
+
+#define CLICK_THRESHOLD_DEFAULT 0.25
+
+static Eina_List *_ecore_fb_li_devices = NULL;
+
+static const char *_ecore_fb_li_kbd_syms[128 * 6] =
+{
+#include "ecore_fb_keytable.h"
+};
+
+/* Initial Copyright (C) Brad Hards (1999-2002),
+ * this function is used to tell if "bit" is set in "array"
+ * it selects a byte from the array, and does a boolean AND
+ * operation with a byte that only has the relevant bit set.
+ * eg. to check for the 12th bit, we do (array[1] & 1<<4).
+ * Moved to static inline in order to force compiler to otimized
+ * the unsued part away or force a link error if long has an unexpected
+ * size.
+ *                                             - bigeasy
+ */
+extern int long_has_neither_32_nor_64_bits(void);
+static inline int test_bit(int bit, unsigned long *array)
+{
+       if (sizeof(long) == 4)
+               return array[bit / 32] & (1 << (bit % 32));
+
+       else if (sizeof(long) == 8)
+               return array[bit / 64] & (1 << (bit % 64));
+
+       else long_has_neither_32_nor_64_bits();
+}
+
+static void 
+_ecore_fb_li_event_free_key_down(void *data, void *ev)
+{
+
+       Ecore_Fb_Event_Key_Up *e;
+
+       e = ev;
+       free(e->keyname);
+       if (e->keysymbol) free(e->keysymbol);
+       if (e->key_compose) free(e->key_compose);
+       free(e);
+}
+
+static void 
+_ecore_fb_li_event_free_key_up(void *data, void *ev)
+{
+
+       Ecore_Fb_Event_Key_Up *e;
+
+       e = ev;
+       free(e->keyname);
+       if (e->keysymbol) free(e->keysymbol);
+       if (e->key_compose) free(e->key_compose);
+       free(e);
+}
+
+static void
+_ecore_fb_li_device_event_key(Ecore_Fb_Input_Device *dev, struct input_event *iev)
+{
+       if(!dev->listen)
+               return;
+
+       /* check for basic keyboard keys */
+       if(iev->code >= KEY_ESC && iev->code <= KEY_COMPOSE)
+       {
+               /* check the key table */
+               if(iev->value)
+               {
+                       int offset = 0;
+                       Ecore_Fb_Event_Key_Down *ev;
+
+                       ev = calloc(1, sizeof(Ecore_Fb_Event_Key_Down));
+                       if(dev->keyboard.shift) offset = 1;
+                       else if(dev->keyboard.lock) offset = 2;
+                       ev->keyname = strdup(_ecore_fb_li_kbd_syms[iev->code * 6]);
+
+                       ev->keysymbol = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + offset]);
+                       ev->key_compose = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + 3 + offset]);
+                       ev->dev = dev;
+                       ecore_event_add(ECORE_FB_EVENT_KEY_DOWN, ev, _ecore_fb_li_event_free_key_down, NULL);
+                       /* its a repeated key, dont increment */
+                       if(iev->value == 2)
+                               return;
+                       if (!strcmp(ev->keyname, "Control_L"))
+                               dev->keyboard.ctrl++;
+                       else if (!strcmp(ev->keyname, "Control_R"))
+                               dev->keyboard.ctrl++;
+                       else if (!strcmp(ev->keyname, "Alt_L"))
+                               dev->keyboard.alt++;
+                       else if (!strcmp(ev->keyname, "Alt_R"))
+                               dev->keyboard.alt++;
+                       else if (!strcmp(ev->keyname, "Shift_L"))
+                               dev->keyboard.shift++;
+                       else if (!strcmp(ev->keyname, "Shift_R"))
+                               dev->keyboard.shift++;
+                       else if (!strcmp(ev->keyname, "Caps_Lock"))
+                               dev->keyboard.lock++;
+                       if (dev->keyboard.ctrl > 2) dev->keyboard.ctrl = 2;
+                       if (dev->keyboard.alt > 2) dev->keyboard.alt = 2;
+                       if (dev->keyboard.shift > 2) dev->keyboard.shift = 2;
+                       if (dev->keyboard.lock > 1) dev->keyboard.lock = 1;
+               }
+               else
+               {
+                       int offset = 0;
+                       Ecore_Fb_Event_Key_Up *ev;
+
+                       ev = calloc(1, sizeof(Ecore_Fb_Event_Key_Up));
+                       if(dev->keyboard.shift) offset = 1;
+                       else if(dev->keyboard.lock) offset = 2;
+                       ev->keyname = strdup(_ecore_fb_li_kbd_syms[iev->code * 6]);
+
+                       ev->keysymbol = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + offset]);
+                       ev->key_compose = strdup(_ecore_fb_li_kbd_syms[(iev->code * 6) + 3 + offset]);
+                       ev->dev = dev;
+                       ecore_event_add(ECORE_FB_EVENT_KEY_UP, ev, _ecore_fb_li_event_free_key_up, NULL);
+                       if (!strcmp(ev->keyname, "Control_L"))
+                               dev->keyboard.ctrl--;
+                       else if (!strcmp(ev->keyname, "Control_R"))
+                               dev->keyboard.ctrl--;
+                       else if (!strcmp(ev->keyname, "Alt_L"))
+                               dev->keyboard.alt--;
+                       else if (!strcmp(ev->keyname, "Alt_R"))
+                               dev->keyboard.alt--;
+                       else if (!strcmp(ev->keyname, "Shift_L"))
+                               dev->keyboard.shift--;
+                       else if (!strcmp(ev->keyname, "Shift_R"))
+                               dev->keyboard.shift--;
+                       else if (!strcmp(ev->keyname, "Caps_Lock"))
+                               dev->keyboard.lock--;
+                       if (dev->keyboard.ctrl < 0) dev->keyboard.ctrl = 0;
+                       if (dev->keyboard.alt < 0) dev->keyboard.alt = 0;
+                       if (dev->keyboard.shift < 0) dev->keyboard.shift = 0;
+                       if (dev->keyboard.lock < 0) dev->keyboard.lock = 0;
+               }
+       }
+       /* check for mouse button events */
+       else if(iev->code >= BTN_MOUSE && iev->code < BTN_JOYSTICK)
+       {
+               int button;
+
+               button = ((iev->code & 0x00F) + 1);
+               if(iev->value)
+               {
+                       Ecore_Fb_Event_Mouse_Button_Down *ev;
+                       double current;
+
+                       ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
+                       ev->dev = dev;
+                       ev->button = button;
+                       ev->x = dev->mouse.x;
+                       ev->y = dev->mouse.y;
+
+                       current = ecore_time_get();
+                       if((current - dev->mouse.prev) <= dev->mouse.threshold)
+                       {
+                               ev->double_click = 1;
+                       }
+                       if((current - dev->mouse.last) <= (2 * dev->mouse.threshold))
+                       {
+                               ev->triple_click = 1;
+                               /* reset */
+                               dev->mouse.prev = 0;
+                               dev->mouse.last = 0;
+                               current = 0;
+                       }
+                       else
+                       {
+                               /* update values */
+                               dev->mouse.last = dev->mouse.prev;
+                               dev->mouse.prev = current;
+                       }
+                       ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, ev, NULL ,NULL);
+               }
+               else
+               {
+                       Ecore_Fb_Event_Mouse_Button_Up *ev;
+
+                       ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Button_Up));
+                       ev->dev = dev;
+                       ev->button = button;
+                       ev->x = dev->mouse.x;
+                       ev->y = dev->mouse.y;
+
+                       ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, ev, NULL ,NULL);
+               }
+       }
+}
+
+static void
+_ecore_fb_li_device_event_rel(Ecore_Fb_Input_Device *dev, struct input_event *iev)
+{
+       if(!dev->listen)
+               return;
+       /* dispatch the button events if they are queued */
+       switch(iev->code)
+       {
+               case REL_X:
+               case REL_Y:
+               {
+                       Ecore_Fb_Event_Mouse_Move *ev;
+                       if(iev->code == REL_X)
+                       {
+                               dev->mouse.x += iev->value;
+                               if(dev->mouse.x > dev->mouse.w - 1)
+                                       dev->mouse.x = dev->mouse.w;
+                               else if(dev->mouse.x < 0)
+                                       dev->mouse.x = 0;
+                       }
+                       else
+                       {
+                               dev->mouse.y += iev->value;
+                               if(dev->mouse.y > dev->mouse.h - 1)
+                                       dev->mouse.y = dev->mouse.h;
+                               else if(dev->mouse.y < 0)
+                                       dev->mouse.y = 0;
+                       }
+                       ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Move));
+                       ev->x = dev->mouse.x;
+                       ev->y = dev->mouse.y;
+                       ev->dev = dev;
+
+                       ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE,ev,NULL,NULL);
+                       break;
+               }
+               case REL_WHEEL:
+               case REL_HWHEEL:
+               {
+                       Ecore_Fb_Event_Mouse_Wheel *ev;
+                       ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Wheel));
+
+                       ev->x = dev->mouse.x;
+                       ev->y = dev->mouse.y;
+                       if(iev->code == REL_HWHEEL)
+                               ev->direction = 1;
+                       ev->wheel = iev->value;
+                       ev->dev = dev;
+                       ecore_event_add(ECORE_FB_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
+                       break;
+               }
+               default:
+                       break;
+       }
+}
+
+static void
+_ecore_fb_li_device_event_abs(Ecore_Fb_Input_Device *dev, struct input_event *iev)
+{
+       static int prev_pressure = 0;
+       int pressure;
+
+       if(!dev->listen)
+               return;
+       switch(iev->code)
+       {
+               case ABS_X:
+                       if(dev->mouse.w != 0)
+                       {
+                               int tmp;
+
+                               tmp = (int)((double)(iev->value - dev->mouse.min_w) / dev->mouse.rel_w);
+                               if(tmp < 0)
+                                       dev->mouse.x = 0;
+                               else if(tmp > dev->mouse.w)
+                                       dev->mouse.x = dev->mouse.w;
+                               else
+                                       dev->mouse.x = tmp;
+                               dev->mouse.event = ECORE_FB_EVENT_MOUSE_MOVE;
+                       }
+                       break;
+
+               case ABS_Y:
+                       if(dev->mouse.h != 0)
+                       {
+                               int tmp;
+
+                               tmp = (int)((double)(iev->value - dev->mouse.min_h) / dev->mouse.rel_h);
+                               if(tmp < 0)
+                                       dev->mouse.y = 0;
+                               else if(tmp > dev->mouse.h)
+                                       dev->mouse.y = dev->mouse.h;
+                               else
+                                       dev->mouse.y = tmp;
+                               dev->mouse.event = ECORE_FB_EVENT_MOUSE_MOVE;
+                       }
+                       break;
+
+               case ABS_PRESSURE:
+                       pressure = iev->value;
+                       if ((pressure) && (!prev_pressure))
+                       {
+                               /* DOWN: mouse is down, but was not now */
+                               dev->mouse.event = ECORE_FB_EVENT_MOUSE_BUTTON_DOWN;
+                       }
+                       else if ((!pressure) && (prev_pressure))
+                       {
+                               /* UP: mouse was down, but is not now */
+                               dev->mouse.event = ECORE_FB_EVENT_MOUSE_BUTTON_UP;
+                       }
+                       prev_pressure = pressure;
+                       break;
+       }
+}
+
+static void
+_ecore_fb_li_device_event_syn(Ecore_Fb_Input_Device *dev, struct input_event *iev)
+{
+       if(!dev->listen)
+               return;
+
+       if(dev->mouse.event == ECORE_FB_EVENT_MOUSE_MOVE)
+       {
+               Ecore_Fb_Event_Mouse_Move *ev;
+               ev = calloc(1,sizeof(Ecore_Fb_Event_Mouse_Move));
+               ev->x = dev->mouse.x;
+               ev->y = dev->mouse.y;
+               ev->dev = dev;
+               ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+       }
+       else if(dev->mouse.event == ECORE_FB_EVENT_MOUSE_BUTTON_DOWN)
+       {
+               Ecore_Fb_Event_Mouse_Button_Down *ev;
+               ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
+               ev->x = dev->mouse.x;
+               ev->y = dev->mouse.y;
+               ev->button = 1;
+               ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
+       }
+       else if(dev->mouse.event == ECORE_FB_EVENT_MOUSE_BUTTON_UP)
+       {
+               Ecore_Fb_Event_Mouse_Button_Up *ev;
+               ev = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up));
+               ev->x = dev->mouse.x;
+               ev->y = dev->mouse.y;
+               ev->button = 1;
+               ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
+       }
+}
+
+static int
+_ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh)
+{
+       Ecore_Fb_Input_Device *dev;
+       struct input_event ev[64];
+       int len;
+       int i;
+
+       dev = (Ecore_Fb_Input_Device*)data;
+       /* read up to 64 events at once */
+       len = read(dev->fd, &ev, sizeof(ev));
+       // printf("[ecore_fb_li_device:fd_callback] received %d data\n", len);
+       for(i = 0; i < len/sizeof(ev[0]); i++)
+       {
+               switch(ev[i].type)
+               {
+                       case EV_SYN:
+                               _ecore_fb_li_device_event_syn(dev, &ev[i]);
+                               break;
+                       case EV_ABS:
+                               _ecore_fb_li_device_event_abs(dev, &ev[i]);
+                               break;
+                       case EV_REL:
+                               _ecore_fb_li_device_event_rel(dev, &ev[i]);
+                               break;
+                       case EV_KEY:
+                               _ecore_fb_li_device_event_key(dev, &ev[i]);
+                               break;
+                       default:
+                               break;
+               }
+       }
+       return 1;
+}
+
+/* 
+ * Starts getting events from the input device 
+ *
+ */
+EAPI void 
+ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, int listen)
+{
+       if(!dev) return;
+       if((listen && dev->listen) || (!listen && !dev->listen)) return;
+       if(listen)
+       {
+               /* if the device already had a handler */
+               if(!dev->handler)
+                       dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL);
+
+       }
+       dev->listen = listen;
+}
+
+#ifndef EV_CNT
+#define EV_CNT (EV_MAX+1)
+#endif
+
+/*
+ * Opens an input device
+ */
+EAPI Ecore_Fb_Input_Device *
+ecore_fb_input_device_open(const char *dev)
+{
+       Ecore_Fb_Input_Device *device;
+       unsigned long event_type_bitmask[EV_CNT / 32 + 1];
+       int event_type;
+       int fd;
+
+       if(!dev) return NULL;
+       device = calloc(1, sizeof(Ecore_Fb_Input_Device));
+       if(!device) return NULL;
+
+       if((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0)
+       {
+               fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno));
+               goto error_open;
+       }
+       /* query capabilities */
+       if(ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0)
+       {
+               fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno));
+               goto error_caps;
+       }
+       /* query name */
+       device->info.name = calloc(256, sizeof(char));
+       if(ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0)
+       {
+               fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno));
+               strcpy(device->info.name, "Unknown");
+       }
+       device->fd = fd;
+       device->info.dev = strdup(dev);
+       /* common */
+       device->mouse.threshold = CLICK_THRESHOLD_DEFAULT;
+
+       /* set info */
+       for(event_type = 0; event_type < EV_MAX; event_type++)
+       {
+               if(!test_bit(event_type, event_type_bitmask))
+                       continue;
+               switch(event_type)
+               {
+                       case EV_SYN :
+                       break;
+
+                       case EV_KEY:
+                       device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS;
+                       break;
+
+                       case EV_REL:
+                       device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE;
+                       break;
+
+                       case EV_ABS:
+                       device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE;
+                       break;
+
+                       case EV_MSC:
+                       case EV_LED:
+                       case EV_SND:
+                       case EV_REP:
+                       case EV_FF :
+                       case EV_FF_STATUS:
+                       case EV_PWR:
+                       default:
+                       break;
+               }
+       }
+       _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device);
+       return device;
+
+       error_caps:
+       close(fd);
+       error_open:
+       free(device);
+       return NULL;
+
+}
+
+EAPI void
+ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev)
+{
+       /* close the fd */
+       close(dev->fd);
+       /* remove the element from the list */
+       _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev);
+       free(dev);
+}
+
+
+/*
+ * If the device is a relative input device, 
+ * we must set a width and height for it. If its
+ * absolute set the ioctl correctly, if not, unsupported
+ * device
+ */
+EAPI void
+ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h)
+{
+       if(!dev)
+               return;
+       if(w < 0 || h < 0)
+               return;
+       /* FIXME 
+        * this code is for a touchscreen device, 
+        * make it configurable (ABSOLUTE | RELATIVE)
+        */
+       if(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE)
+       {
+               /* FIXME looks like some kernels dont include this struct */
+               struct input_absinfo abs_features;
+
+               ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features);
+               dev->mouse.min_w = abs_features.minimum;
+               dev->mouse.rel_w = (double)(abs_features.maximum - abs_features.minimum)/(double)(w);
+
+               ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features);
+               dev->mouse.min_h = abs_features.minimum;
+               dev->mouse.rel_h = (double)(abs_features.maximum - abs_features.minimum)/(double)(h);
+       }
+       else if(!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE))
+               return;
+
+       /* update the local values */
+       if(dev->mouse.x > w - 1)
+               dev->mouse.x = w -1;
+       if(dev->mouse.y > h - 1)
+               dev->mouse.y = h -1;
+       dev->mouse.w = w;
+       dev->mouse.h = h;
+}
+
+
+EAPI const char *
+ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev)
+{
+       if(!dev)
+               return NULL;
+       return dev->info.name;
+}
+EAPI Ecore_Fb_Input_Device_Cap
+ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev)
+{
+       if(!dev)
+               return ECORE_FB_INPUT_DEVICE_CAP_NONE;
+       return dev->info.cap;
+}
+EAPI void
+ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold)
+{
+       if(!dev) return;
+       if(threshold == dev->mouse.threshold || threshold == 0) return;
+       dev->mouse.threshold = threshold;
+}
+EAPI double
+ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev)
+{
+       if(!dev) return 0;
+       return dev->mouse.threshold;
+}
diff --git a/src/lib/ecore_fb/ecore_fb_private.h b/src/lib/ecore_fb/ecore_fb_private.h
new file mode 100644 (file)
index 0000000..121f69e
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef _ECORE_FB_PRIVATE_H
+#define _ECORE_FB_PRIVATE_H
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/version.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <linux/fb.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+ #define kernel_ulong_t unsigned long 
+ #define BITS_PER_LONG 32
+ #include <linux/input.h>
+ #undef kernel_ulong_t
+ #undef BITS_PER_LONG
+#else
+ #include <linux/input.h>
+#endif
+
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* ecore_fb_li.c */
+struct _Ecore_Fb_Input_Device
+{
+       int fd;
+       Ecore_Fd_Handler *handler;
+       int listen;
+       struct {
+               Ecore_Fb_Input_Device_Cap cap;
+               char *name;
+               char *dev;
+       } info;
+       struct
+       {
+               /* common mouse */
+               int x,y;
+               int w,h;
+               
+               double last;
+               double prev;
+               double threshold;
+               /* absolute axis */
+               int min_w, min_h;
+               double rel_w, rel_h;
+               int event;
+       } mouse;
+       struct
+       {
+               int shift;
+               int ctrl;
+               int alt;
+               int lock;
+       } keyboard;
+};
+
+/* ecore_fb_ts.c */
+EAPI int    ecore_fb_ts_init(void);
+EAPI void   ecore_fb_ts_shutdown(void);
+
+/* ecore_fb_vt.c */
+int  ecore_fb_vt_init(void);
+void ecore_fb_vt_shutdown(void);
+
+/* hacks to stop people NEEDING #include <linux/h3600_ts.h> */
+#ifndef TS_SET_CAL
+#define TS_SET_CAL 0x4014660b
+#endif
+#ifndef TS_GET_CAL
+#define TS_GET_CAL 0x8014660a
+#endif
+  
+#endif
diff --git a/src/lib/ecore_fb/ecore_fb_ps2.c b/src/lib/ecore_fb/ecore_fb_ps2.c
new file mode 100644 (file)
index 0000000..3a062da
--- /dev/null
@@ -0,0 +1,185 @@
+typedef struct _Ecore_Fb_Ps2_Event Ecore_Fb_Ps2_Event;
+struct _Ecore_Fb_Ps2_Event
+{
+   unsigned char button;
+   unsigned char x;
+   unsigned char y;
+   unsigned char z;
+};
+
+static int _ecore_fb_ps2_event_byte_count = 0;
+static Ecore_Fb_Ps2_Event _ecore_fb_ps2_event;
+static int _ecore_fb_ps2_fd = 0;
+static int _ecore_fb_ps2_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
+int
+ecore_fb_ps2_init(void)
+{
+   _ecore_fb_ps2_fd = open("/dev/psaux", O_RDWR);
+   if (_ecore_fb_ps2_fd >= 0)
+     {
+       prev_flags = fcntl(_ecore_fb_ps2_fd, F_GETFL);
+       fcntl(_ecore_fb_ps2_fd, F_SETFL, prev_flags | O_NONBLOCK);
+       _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ps2_fd, 
+                                                                       ECORE_FD_READ,
+                                                                       _ecore_fb_ps2_fd_handler, NULL, NULL, NULL);
+       if (!_ecore_fb_ts_fd_handler_handle)
+        {
+          close(_ecore_fb_ps2_fd);
+          return 0;
+         }
+       return 1;
+     }
+  return 0;   
+}
+
+void
+ecore_fb_ps2_shutdown(void)
+{
+   if (_ecore_fb_ps2_fd > 0) close(_ecore_fb_ps2_fd);
+   _ecore_fb_ps2_fd = 0;
+}
+
+static int
+_ecore_fb_ps2_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   static int prev_x = 0, prev_y = 0, prev_button = 0;
+   static double last_time = 0;
+   static double last_last_time = 0;
+   int v = 0;
+
+   do
+     {
+       int x, y, button, i;
+       int num;
+       char *ptr;
+       double t;
+       int did_triple = 0;
+       
+       ptr = (char *)&(_ecore_fb_ps2_event);
+       ptr += _ecore_fb_ps2_event_byte_count;
+       num = sizeof(Ecore_Fb_Ps2_Event) - _ecore_fb_ps2_event_byte_count;
+       v = read(_ecore_fb_ps2_fd, ptr, num);
+       if (v < 0) return 1;
+       _ecore_fb_ps2_event_byte_count += v;
+       if (v < num) return 1;
+       t = ecore_time_get();
+       _ecore_fb_ps2_event_byte_count = 0;
+       if (_ecore_fb_ps2_event.button & 0x10)
+         x = prev_x + (0xffffff00 | _ecore_fb_ps2_event.x);
+       else
+         x = prev_x + _ecore_fb_ps2_event.x;
+       if (_ecore_fb_ps2_event.button & 0x20)
+         y = prev_y - (0xffffff00 | _ecore_fb_ps2_event.y);
+       else
+         y = prev_y - _ecore_fb_ps2_event.y;
+       button = _ecore_fb_ps2_event.button & 0x7;
+       if (x < 0) x = 0;
+       if (y < 0) y = 0;
+       if (x >= _ecore_fb_console_w) x = _ecore_fb_console_w - 1;
+       if (y >= _ecore_fb_console_h) y = _ecore_fb_console_h - 1;
+       /* add event to queue */
+       /* always add a move event */
+       if (1)
+         {
+            /* MOVE: mouse is down and was */
+            Ecore_Fb_Event_Mouse_Move *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move));
+            if (!e) goto retry;
+            e->x = x;
+            e->y = y;
+            ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, e, NULL, NULL);
+         }
+       for (i = 1; i <= 3; i++)
+         {
+            int mask;
+            
+            mask = 1 << (i - 1);
+            if (((button & mask)) && (!(prev_button & mask)))
+              {
+                 /* DOWN: mouse is down, but was not now */
+                 Ecore_Fb_Event_Mouse_Button_Down *e;
+                 
+                 e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
+                 if (!e) goto retry;
+                 e->x = x;
+                 e->y = y;
+                 e->button = 1;
+                 if ((t - last_time) <= _ecore_fb_double_click_time)
+                   e->double_click = 1;
+                 if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time))
+                   {
+                      did_triple = 1;
+                      e->triple_click = 1;
+                   }
+                 ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
+              }
+            else if ((!(button & mask)) && ((prev_button & mask)))
+              {
+                 /* UP: mouse was down, but is not now */
+                 Ecore_Fb_Event_Mouse_Button_Up *e;
+                 
+                 e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up));
+                 if (!e) goto retry;
+                 e->x = x;
+                 e->y = y;
+                 e->button = 1;
+                 ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
+              }
+         }
+       if (did_triple)
+         {
+            last_time = 0;
+            last_last_time = 0;
+         }
+       else
+         {
+            last_last_time = last_time;
+            last_time = t;
+         }
+       retry:       
+       prev_x = x;
+       prev_y = y;
+       prev_button = button;
+     }
+   while (v > 0);
+   return 1;
+}
+/**
+ * @defgroup Ecore_FB_Click_Group Framebuffer Double Click Functions
+ *
+ * Functions that deal with the double click time of the framebuffer.
+ */
+
+/**
+ * Sets the timeout for a double and triple clicks to be flagged.
+ * 
+ * This sets the time between clicks before the double_click flag is
+ * set in a button down event. If 3 clicks occur within double this
+ * time, the triple_click flag is also set.
+ *
+ * @param   t The time in seconds
+ * @ingroup Ecore_FB_Click_Group
+ */
+EAPI void
+ecore_fb_double_click_time_set(double t)
+{
+   if (t < 0.0) t = 0.0;
+   _ecore_fb_double_click_time = t;
+}
+
+/**
+ * Retrieves the double and triple click flag timeout.
+ *
+ * See @ref ecore_x_double_click_time_set for more information.
+ *
+ * @return  The timeout for double clicks in seconds.
+ * @ingroup Ecore_FB_Click_Group
+ */
+EAPI double
+ecore_fb_double_click_time_get(void)
+{
+   return _ecore_fb_double_click_time;
+}
+
diff --git a/src/lib/ecore_fb/ecore_fb_ts.c b/src/lib/ecore_fb/ecore_fb_ts.c
new file mode 100644 (file)
index 0000000..cb9eff6
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_TSLIB
+# include <tslib.h>
+# include <errno.h>
+#endif
+
+#include "Ecore_Fb.h"
+#include "ecore_fb_private.h"
+
+typedef struct _Ecore_Fb_Ts_Event Ecore_Fb_Ts_Event;
+typedef struct _Ecore_Fb_Ts_Calibrate Ecore_Fb_Ts_Calibrate;
+typedef struct _Ecore_Fb_Ts_Backlight Ecore_Fb_Ts_Backlight;
+typedef struct _Ecore_Fb_Ts_Contrast Ecore_Fb_Ts_Contrast;
+typedef struct _Ecore_Fb_Ts_Led Ecore_Fb_Ts_Led;
+typedef struct _Ecore_Fb_Ts_Flite Ecore_Fb_Ts_Flite;
+
+struct _Ecore_Fb_Ts_Event
+{
+   unsigned short pressure;
+   unsigned short x;
+   unsigned short y;
+   unsigned short _unused; 
+};
+
+struct _Ecore_Fb_Ts_Calibrate
+{
+   int xscale;
+   int xtrans;
+   int yscale;
+   int ytrans;
+   int xyswap;
+};
+
+struct _Ecore_Fb_Ts_Backlight
+{
+   int           on;
+   unsigned char brightness;
+};
+
+struct _Ecore_Fb_Ts_Contrast
+{
+   unsigned char contrast;
+};
+
+struct _Ecore_Fb_Ts_Led
+{
+   unsigned char on;
+   unsigned char blink_time;
+   unsigned char on_time;
+   unsigned char off_time;
+};
+
+struct _Ecore_Fb_Ts_Flite
+{
+   unsigned char mode;
+   unsigned char pwr;
+   unsigned char brightness;
+};
+
+static int _ecore_fb_ts_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_fb_ts_fd = -1;
+static int _ecore_fb_ts_event_byte_count = 0;
+static int _ecore_fb_ts_apply_cal = 0;
+static Ecore_Fb_Ts_Event _ecore_fb_ts_event;
+static Ecore_Fb_Ts_Calibrate _ecore_fb_ts_cal = {1,1,0,0,0};
+static Ecore_Fd_Handler *_ecore_fb_ts_fd_handler_handle = NULL;
+
+#ifdef HAVE_TSLIB
+struct tsdev *_ecore_fb_tslib_tsdev = NULL;
+struct ts_sample _ecore_fb_tslib_event;
+#endif
+
+static double _ecore_fb_double_click_time = 0.25;
+
+EAPI int
+ecore_fb_ts_init(void)
+{
+#ifdef HAVE_TSLIB
+   char *tslib_tsdevice = NULL;
+   if ( ( tslib_tsdevice = getenv("TSLIB_TSDEVICE") ) != NULL )
+    {
+        printf( "ECORE_FB: TSLIB_TSDEVICE = '%s'\n", tslib_tsdevice );
+        _ecore_fb_tslib_tsdev = ts_open( tslib_tsdevice, 1 ); /* 1 = nonblocking, 0 = blocking */
+
+        if ( !_ecore_fb_tslib_tsdev )
+        {
+            printf( "ECORE_FB: Can't ts_open (%s)\n", strerror( errno ) );
+            return 0;
+        }
+
+        if ( ts_config( _ecore_fb_tslib_tsdev ) )
+        {
+            printf( "ECORE_FB: Can't ts_config (%s)\n", strerror( errno ) );
+            return 0;
+        }
+        _ecore_fb_ts_fd = ts_fd( _ecore_fb_tslib_tsdev );
+        if ( _ecore_fb_ts_fd < 0 )
+        {
+            printf( "ECORE_FB: Can't open touchscreen (%s)\n", strerror( errno ) );
+            return 0;
+        }
+    }
+#else
+   _ecore_fb_ts_fd = open("/dev/touchscreen/0", O_RDONLY);
+#endif
+   if (_ecore_fb_ts_fd >= 0)
+     {
+       _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ts_fd, 
+                                                                  ECORE_FD_READ,
+                                                                  _ecore_fb_ts_fd_handler, NULL,
+                                                                  NULL, NULL);
+       if (!_ecore_fb_ts_fd_handler_handle)
+         {
+            close(_ecore_fb_ts_fd);
+            return 0;
+         }
+       // FIXME _ecore_fb_kbd_fd = open("/dev/touchscreen/key", O_RDONLY);
+       return 1;
+     }
+   return 0;
+}
+
+EAPI void
+ecore_fb_ts_shutdown(void)
+{
+   if (_ecore_fb_ts_fd >= 0) close(_ecore_fb_ts_fd);
+   if (_ecore_fb_ts_fd_handler_handle)
+     ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle);
+   _ecore_fb_ts_fd = -1;
+   _ecore_fb_ts_fd_handler_handle = NULL;
+}
+
+/**
+ * @defgroup Ecore_FB_Calibrate_Group Framebuffer Calibration Functions
+ *
+ * Functions that calibrate the screen.
+ */
+  
+  
+/**
+ * Calibrates the touschreen using the given parameters.
+ * @param   xscale X scaling, where 256 = 1.0
+ * @param   xtrans X translation.
+ * @param   yscale Y scaling.
+ * @param   ytrans Y translation.
+ * @param   xyswap Swap X & Y flag.
+ * @ingroup Ecore_FB_Calibrate_Group
+ */
+EAPI void
+ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap)
+{
+   Ecore_Fb_Ts_Calibrate cal;
+   
+   if (_ecore_fb_ts_fd < 0) return;
+   cal.xscale = xscale;
+   cal.xtrans = xtrans;
+   cal.yscale = yscale;
+   cal.ytrans = ytrans;
+   cal.xyswap = xyswap;
+   if (ioctl(_ecore_fb_ts_fd, TS_SET_CAL, (void *)&cal))
+     {
+       _ecore_fb_ts_cal = cal;
+       _ecore_fb_ts_apply_cal = 1;
+       
+     }
+}
+
+/**
+ * Retrieves the calibration parameters of the touchscreen.
+ * @param   xscale Pointer to an integer in which to store the X scaling.
+ *                 Note that 256 = 1.0.
+ * @param   xtrans Pointer to an integer in which to store the X translation.
+ * @param   yscale Pointer to an integer in which to store the Y scaling.
+ * @param   ytrans Pointer to an integer in which to store the Y translation.
+ * @param   xyswap Pointer to an integer in which to store the Swap X & Y flag.
+ * @ingroup Ecore_FB_Calibrate_Group
+ */
+EAPI void
+ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap)
+{
+   Ecore_Fb_Ts_Calibrate cal;
+   
+   if (_ecore_fb_ts_fd < 0) return;
+   if (!_ecore_fb_ts_apply_cal)
+     {
+       if (ioctl(_ecore_fb_ts_fd, TS_GET_CAL, (void *)&cal))
+         _ecore_fb_ts_cal = cal;
+       
+     }
+   else
+     cal = _ecore_fb_ts_cal;
+   if (xscale) *xscale = cal.xscale;
+   if (xtrans) *xtrans = cal.xtrans;
+   if (yscale) *yscale = cal.yscale;
+   if (ytrans) *ytrans = cal.ytrans;
+   if (xyswap) *xyswap = cal.xyswap;
+}
+
+static int
+_ecore_fb_ts_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   static int prev_x = 0, prev_y = 0, prev_pressure = 0;
+   static double last_time = 0;
+   static double last_last_time = 0;
+   int v = 0;
+   
+   do
+     {
+       int x, y, pressure;
+       int num;
+       char *ptr;
+       double t;
+       int did_triple = 0;
+
+#ifdef HAVE_TSLIB
+       if (_ecore_fb_ts_apply_cal)
+         num = ts_read_raw(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1);
+       else
+         num = ts_read(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1);
+       if (num != 1) return 1; /* no more samples at this time */
+       x = _ecore_fb_tslib_event.x;
+       y = _ecore_fb_tslib_event.y;
+       pressure = _ecore_fb_tslib_event.pressure;
+       v = 1; /* loop, there might be more samples */
+       t = ecore_time_get();
+#else
+       ptr = (char *)&(_ecore_fb_ts_event);
+       ptr += _ecore_fb_ts_event_byte_count;
+       num = sizeof(Ecore_Fb_Ts_Event) - _ecore_fb_ts_event_byte_count;
+       v = read(_ecore_fb_ts_fd, ptr, num);
+       if (v < 0) return 1;
+       _ecore_fb_ts_event_byte_count += v;
+       if (v < num) return 1;
+       _ecore_fb_ts_event_byte_count = 0;
+       if (_ecore_fb_ts_apply_cal)
+         {
+            x = ((_ecore_fb_ts_cal.xscale * _ecore_fb_ts_event.x) >> 8) + _ecore_fb_ts_cal.xtrans;
+            y = ((_ecore_fb_ts_cal.yscale * _ecore_fb_ts_event.y) >> 8) + _ecore_fb_ts_cal.ytrans;
+         }
+       else
+         {
+            x = _ecore_fb_ts_event.x;
+            y = _ecore_fb_ts_event.y;
+         }
+       pressure = _ecore_fb_ts_event.pressure;
+#endif   
+       /* add event to queue */
+       /* always add a move event */
+       if ((pressure) || (prev_pressure))
+         {
+            /* MOVE: mouse is down and was */
+            Ecore_Fb_Event_Mouse_Move *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move));
+            if (!e) goto retry;
+            e->x = x;
+            e->y = y;
+            ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, e, NULL, NULL);
+         }
+       if ((pressure) && (!prev_pressure))
+         {
+            /* DOWN: mouse is down, but was not now */
+            Ecore_Fb_Event_Mouse_Button_Down *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down));
+            if (!e) goto retry;
+            e->x = x;
+            e->y = y;
+            e->button = 1;
+            if ((t - last_time) <= _ecore_fb_double_click_time)
+              e->double_click = 1;
+            if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time))
+              {
+                 did_triple = 1;
+                 e->triple_click = 1;
+              }
+            ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
+         }
+       else if ((!pressure) && (prev_pressure))
+         {
+            /* UP: mouse was down, but is not now */
+            Ecore_Fb_Event_Mouse_Button_Up *e;
+            
+            e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up));
+            if (!e) goto retry;
+            e->x = prev_x;
+            e->y = prev_y;
+            e->button = 1;
+            ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
+         }
+        if (did_triple)
+         {
+            last_time = 0;
+            last_last_time = 0;
+         }
+       else
+         {
+            last_last_time = last_time;
+            last_time = t;
+         }
+       retry:       
+       prev_x = x;
+       prev_y = y;
+       prev_pressure = pressure;
+     }
+   while (v > 0);
+   return 1;
+}
+
diff --git a/src/lib/ecore_fb/ecore_fb_vt.c b/src/lib/ecore_fb/ecore_fb_vt.c
new file mode 100644 (file)
index 0000000..972aa9b
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore_Fb.h"
+#include "ecore_fb_private.h"
+
+static int _ecore_fb_vt_do_switch = 0;
+
+static int _ecore_fb_vt_tty0_fd = 0;
+static int _ecore_fb_vt_tty_fd = 0;
+static int _ecore_fb_vt_current_vt = 0;
+static int _ecore_fb_vt_prev_vt = 0;
+
+static struct termios _ecore_fb_tty_prev_tio_mode;
+static struct vt_mode _ecore_fb_vt_prev_mode;
+
+static int _ecore_fb_signal_usr_handler(void *data, int type, void *ev);
+static Ecore_Event_Handler *_ecore_fb_user_handler = NULL;
+static int _ecore_fb_tty_prev_mode = 0;
+static int _ecore_fb_tty_prev_kd_mode = 0;
+
+/* callbacks for an attach/release of a vt */
+static void (*_ecore_fb_func_fb_lost) (void *data) = NULL;
+static void *_ecore_fb_func_fb_lost_data = NULL;
+static void (*_ecore_fb_func_fb_gain) (void *data) = NULL;
+static void *_ecore_fb_func_fb_gain_data = NULL;
+
+/* FIXME what is the filter for? */
+static Ecore_Event_Filter *_ecore_fb_filter_handler = NULL;
+
+static void *_ecore_fb_event_filter_start(void *data);
+static int   _ecore_fb_event_filter_filter(void *data, void *loop_data, int type, void *event);
+static void  _ecore_fb_event_filter_end(void *data, void *loop_data);
+
+/* prototypes */
+static void _ecore_fb_vt_switch(int vt);
+
+static int
+_ecore_fb_signal_usr_handler(void *data __UNUSED__, int type __UNUSED__, void *ev)
+{
+
+       Ecore_Event_Signal_User *e;
+   
+       e = (Ecore_Event_Signal_User *)ev;
+       if (e->number == 1)
+       {
+               /* release vt */
+               if (_ecore_fb_func_fb_lost) _ecore_fb_func_fb_lost(_ecore_fb_func_fb_lost_data);
+               /* TODO stop listening from the devices? let the callback do it? */
+               ioctl(_ecore_fb_vt_tty_fd, VT_RELDISP, 1);
+       }
+       else if (e->number == 2)
+       {
+               /* attach vt */
+               if (_ecore_fb_func_fb_gain) _ecore_fb_func_fb_gain(_ecore_fb_func_fb_gain_data);
+               /* TODO reattach all devices */
+       }
+       return 1;
+}
+
+static void
+_ecore_fb_vt_switch(int vt)
+{
+       vt++;
+       if (_ecore_fb_vt_tty_fd != 0)
+       {
+               if (vt != _ecore_fb_vt_current_vt)
+               {
+                       tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode);
+                       ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode);
+                       ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode);
+               }
+       }
+       ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, vt);
+}
+
+static int
+_ecore_fb_vt_setup(void)
+{
+       char buf[64];
+       struct termios tio;
+       struct vt_mode new_vtmode;
+
+       if(_ecore_fb_vt_current_vt != _ecore_fb_vt_prev_vt)
+       {
+               snprintf(buf, sizeof(buf), "/dev/tty%i", _ecore_fb_vt_current_vt);
+               if((_ecore_fb_vt_tty_fd = open(buf, O_RDWR)) < 0)
+               {
+                       printf("[ecore_fb:vt_setup] cant open tty %d\n", _ecore_fb_vt_current_vt);
+                       return 0;
+               }
+               close(_ecore_fb_vt_tty0_fd);
+               _ecore_fb_vt_tty0_fd = 0;
+               /* FIXME detach the process from current tty ? */
+       }
+       else
+               _ecore_fb_vt_tty_fd = _ecore_fb_vt_tty0_fd;
+       /* for backup */
+       tcgetattr(_ecore_fb_vt_tty_fd, &_ecore_fb_tty_prev_tio_mode);
+       ioctl(_ecore_fb_vt_tty_fd, KDGETMODE, &_ecore_fb_tty_prev_kd_mode);
+       ioctl(_ecore_fb_vt_tty_fd, VT_GETMODE, &_ecore_fb_vt_prev_mode);
+
+       if(ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, KD_GRAPHICS) < 0)
+       {
+               perror("[ecore_fb:vt_setup] cant set the mode to KD_GRAPHICS");
+               close(_ecore_fb_vt_tty_fd);
+               return 0;
+       }
+       ioctl(_ecore_fb_vt_tty_fd, KDGKBMODE, &_ecore_fb_tty_prev_mode);
+       
+       /* support of switching */
+       new_vtmode.mode = VT_PROCESS;
+       new_vtmode.waitv = 0;
+       new_vtmode.relsig = SIGUSR1;
+       new_vtmode.acqsig = SIGUSR2;
+       if(ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &new_vtmode) < 0)
+       {
+               perror("[ecore_fb:vt_setup] cant set the tty mode");
+               close(_ecore_fb_vt_tty_fd);
+               return 0;
+       }
+       /* register signal handlers when alloc/detach of vt */
+       _ecore_fb_user_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
+                                                   _ecore_fb_signal_usr_handler,
+                                                   NULL);
+       /* What does this does? */
+       _ecore_fb_filter_handler = ecore_event_filter_add(_ecore_fb_event_filter_start, _ecore_fb_event_filter_filter, _ecore_fb_event_filter_end, NULL);
+       
+       usleep(40000);
+       if(ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, _ecore_fb_vt_current_vt) < 0)
+       {
+               perror("[ecore_fb:vt_setup] error on VT_ACTIVATE");
+               close(_ecore_fb_vt_tty_fd);
+               return 0;
+       }
+       if(ioctl(_ecore_fb_vt_tty_fd, VT_WAITACTIVE, _ecore_fb_vt_current_vt) < 0)
+       {
+               perror("[ecore_fb:vt_setup] error on VT_WAITACTIVE");
+               close(_ecore_fb_vt_tty_fd);
+               return 0;
+       }
+       /* FIXME assign the fb to the tty in case isnt setup */
+       return 1;
+}
+
+int
+ecore_fb_vt_init(void)
+{
+       struct vt_stat vtstat;
+
+       /* as root you can allocate another tty */
+       if(!geteuid())
+               _ecore_fb_vt_do_switch = 1;
+       if((_ecore_fb_vt_tty0_fd = open("/dev/tty0", O_RDONLY)) < 0)
+       {
+               printf("[ecore_fb:init] cant open /dev/tty0\n");
+               return 0;
+       }
+       /* query current vt state */
+       if((ioctl(_ecore_fb_vt_tty0_fd, VT_GETSTATE, &vtstat)) < 0)
+       {
+               printf("[ecore_fb:init] cant get current tty state\n");
+               return 0;
+       }
+       _ecore_fb_vt_prev_vt = vtstat.v_active;
+       /* switch to another tty */
+       if(_ecore_fb_vt_do_switch)
+       {
+               int vtno;
+
+               if ((ioctl(_ecore_fb_vt_tty0_fd, VT_OPENQRY, &vtno) < 0))
+               {
+                       printf("[ecore_fb:init] cant query for a vt\n");
+                       return 0;
+               }
+               _ecore_fb_vt_current_vt = vtno;
+       }
+       /* use current tty */
+       else
+               _ecore_fb_vt_current_vt = _ecore_fb_vt_prev_vt;
+       if(!_ecore_fb_vt_setup())
+       {
+               printf("[ecore_fb:init] cant setup the vt, restoring previous mode...\n");
+               /* TODO finish this */
+               if(_ecore_fb_vt_do_switch)
+               {
+                       printf("[ecore_fb:init] switching back to vt %d\n", _ecore_fb_vt_prev_vt);
+               }
+               return 0;
+       }
+       return 1;
+}
+
+void
+ecore_fb_vt_shutdown(void)
+{
+       /* restore the previous mode */
+       if(_ecore_fb_vt_tty_fd != 0)
+       {
+               tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode);
+               ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode);
+               ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode);
+               ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &_ecore_fb_vt_prev_mode);
+               /* go back to previous vt */
+               close(_ecore_fb_vt_tty_fd);
+               _ecore_fb_vt_tty_fd = 0;
+       }
+       
+       if(_ecore_fb_user_handler)
+               ecore_event_handler_del(_ecore_fb_user_handler);
+       _ecore_fb_user_handler = NULL;
+
+       if(_ecore_fb_filter_handler)
+               ecore_event_filter_del(_ecore_fb_filter_handler);
+       _ecore_fb_filter_handler = NULL;
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ * @todo Documentation: Find out what this does.
+ */
+EAPI void
+ecore_fb_callback_gain_set(void (*func) (void *data), void *data)
+{
+   _ecore_fb_func_fb_gain = func;
+   _ecore_fb_func_fb_gain_data = data;
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ * @todo Documentation: Find out what this does.
+ */
+EAPI void
+ecore_fb_callback_lose_set(void (*func) (void *data), void *data)
+{
+   _ecore_fb_func_fb_lost = func;
+   _ecore_fb_func_fb_lost_data = data;
+}
+typedef struct _Ecore_Fb_Filter_Data Ecore_Fb_Filter_Data;
+   
+struct _Ecore_Fb_Filter_Data
+{
+   int last_event_type;
+};
+                
+static void *
+_ecore_fb_event_filter_start(void *data __UNUSED__)
+{
+   Ecore_Fb_Filter_Data *filter_data;
+   
+   filter_data = calloc(1, sizeof(Ecore_Fb_Filter_Data));
+   return filter_data;
+}
+
+static int
+_ecore_fb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__)
+{
+   Ecore_Fb_Filter_Data *filter_data;
+   
+   filter_data = loop_data;
+   if (!filter_data) return 1;
+   if (type == ECORE_FB_EVENT_MOUSE_MOVE)
+     {
+       if ((filter_data->last_event_type) == ECORE_FB_EVENT_MOUSE_MOVE)
+         {
+            filter_data->last_event_type = type;
+            return 0;
+         }
+     }
+   filter_data->last_event_type = type;
+   return 1;
+}
+
+static void
+_ecore_fb_event_filter_end(void *data __UNUSED__, void *loop_data)
+{
+   Ecore_Fb_Filter_Data *filter_data;
+   
+   filter_data = loop_data;
+   if (filter_data) free(filter_data);
+}
diff --git a/src/lib/ecore_file/.cvsignore b/src/lib/ecore_file/.cvsignore
new file mode 100644 (file)
index 0000000..be74149
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_file.la
diff --git a/src/lib/ecore_file/Ecore_File.h b/src/lib/ecore_file/Ecore_File.h
new file mode 100644 (file)
index 0000000..144117d
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef ECORE_FILE_H
+#define ECORE_FILE_H
+
+/*
+ * TODO:
+ * - More events, move/rename of directory file
+ */
+
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_FILE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_FILE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file Ecore_File.h
+ * @brief Files utility functions
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   typedef struct _Ecore_File_Monitor       Ecore_File_Monitor;
+   typedef struct _Ecore_File_Monitor_Event Ecore_File_Monitor_Event;
+   typedef struct _Ecore_File_Download_Job  Ecore_File_Download_Job;
+
+   typedef enum
+     {
+       ECORE_FILE_EVENT_NONE,
+         ECORE_FILE_EVENT_CREATED_FILE,
+         ECORE_FILE_EVENT_CREATED_DIRECTORY,
+         ECORE_FILE_EVENT_DELETED_FILE,
+         ECORE_FILE_EVENT_DELETED_DIRECTORY,
+         ECORE_FILE_EVENT_DELETED_SELF,
+         ECORE_FILE_EVENT_MODIFIED
+     } Ecore_File_Event;
+
+
+   EAPI int         ecore_file_init         (void);
+   EAPI int         ecore_file_shutdown     (void);
+   EAPI long long   ecore_file_mod_time     (const char *file);
+   EAPI long long   ecore_file_size         (const char *file);
+   EAPI int         ecore_file_exists       (const char *file);
+   EAPI int         ecore_file_is_dir       (const char *file);
+   EAPI int         ecore_file_mkdir        (const char *dir);
+   EAPI int         ecore_file_mkdirs       (const char **dirs);
+   EAPI int         ecore_file_mksubdirs    (const char *base, const char **subdirs);
+   EAPI int         ecore_file_rmdir        (const char *dir);
+   EAPI int         ecore_file_recursive_rm (const char *dir);
+   EAPI int         ecore_file_mkpath       (const char *path);
+   EAPI int         ecore_file_mkpaths      (const char **paths);
+   EAPI int         ecore_file_cp           (const char *src, const char *dst);
+   EAPI int         ecore_file_mv           (const char *src, const char *dst);
+   EAPI int         ecore_file_symlink      (const char *src, const char *dest);
+   EAPI char       *ecore_file_realpath     (const char *file);
+   EAPI int         ecore_file_unlink       (const char *file);
+   EAPI int         ecore_file_remove       (const char *file);
+   EAPI const char *ecore_file_file_get     (const char *path);
+   EAPI char       *ecore_file_dir_get      (const char *path);
+
+   EAPI int         ecore_file_can_read     (const char *file);
+   EAPI int         ecore_file_can_write    (const char *file);
+   EAPI int         ecore_file_can_exec     (const char *file);
+   EAPI char       *ecore_file_readlink     (const char *link);
+   EAPI Eina_List  *ecore_file_ls           (const char *dir);
+   EAPI char       *ecore_file_app_exe_get  (const char *app);
+   EAPI char       *ecore_file_escape_name  (const char *filename);
+   EAPI char       *ecore_file_strip_ext    (const char *file);
+   EAPI int         ecore_file_dir_is_empty (const char *dir);
+
+   EAPI Ecore_File_Monitor * ecore_file_monitor_add(const char *path,
+                void (*func) (void *data, Ecore_File_Monitor *em,
+                      Ecore_File_Event event,
+                      const char *path),
+                void *data);
+   EAPI void        ecore_file_monitor_del(Ecore_File_Monitor *ecore_file_monitor);
+   EAPI const char *ecore_file_monitor_path_get(Ecore_File_Monitor *ecore_file_monitor);
+
+   EAPI int         ecore_file_path_dir_exists(const char *in_dir);
+   EAPI int         ecore_file_app_installed(const char *exe);
+   EAPI Eina_List  *ecore_file_app_list(void);
+
+   EAPI int ecore_file_download(const char *url, const char *dst, 
+                                       void (*completion_cb)(void *data,
+                                                             const char *file,
+                                                             int status),
+                                       int (*progress_cb)(void *data,
+                                                          const char *file,
+                                                          long int dltotal,
+                                                          long int dlnow,
+                                                          long int ultotal,
+                                                          long int ulnow),
+                                       void *data, 
+                                       Ecore_File_Download_Job **job_ret);
+   EAPI void        ecore_file_download_abort_all(void);  
+   EAPI void        ecore_file_download_abort(Ecore_File_Download_Job *job);
+   EAPI int         ecore_file_download_protocol_available(const char *protocol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_file/Makefile.am b/src/lib/ecore_file/Makefile.am
new file mode 100644 (file)
index 0000000..fff3591
--- /dev/null
@@ -0,0 +1,44 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_con \
+-I$(top_builddir)/src/lib/ecore \
+@EFL_ECORE_FILE_BUILD@ \
+@CURL_CFLAGS@ \
+@EVIL_CFLAGS@ \
+@EINA_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+AM_CFLAGS = @WIN32_CFLAGS@
+
+if BUILD_ECORE_CON
+lib_ecore_con_la = $(top_builddir)/src/lib/ecore_con/libecore_con.la
+endif
+
+if BUILD_ECORE_FILE
+
+lib_LTLIBRARIES = libecore_file.la
+include_HEADERS = Ecore_File.h
+
+libecore_file_la_SOURCES = \
+ecore_file.c \
+ecore_file_monitor.c \
+ecore_file_monitor_inotify.c \
+ecore_file_monitor_win32.c \
+ecore_file_monitor_poll.c \
+ecore_file_path.c \
+ecore_file_download.c
+
+libecore_file_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(lib_ecore_con_la) \
+@EVIL_LIBS@ \
+@EINA_LIBS@
+
+libecore_file_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_file_release_info@
+
+endif
+
+EXTRA_DIST = ecore_file_private.h
+
diff --git a/src/lib/ecore_file/ecore_file.c b/src/lib/ecore_file/ecore_file.c
new file mode 100644 (file)
index 0000000..385307a
--- /dev/null
@@ -0,0 +1,941 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#ifndef _MSC_VER
+# include <unistd.h>
+# include <libgen.h>
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS  64
+#endif
+
+#ifdef HAVE_FEATURES_H
+# include <features.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+
+#include "ecore_file_private.h"
+
+int _ecore_file_log_dom = -1;
+static int _ecore_file_init_count = 0;
+
+/* externally accessible functions */
+/**
+ * Initialize Ecore_File and the services it will use. Call this function
+ * once before you use any of the ecore file functions.
+ * @return Return the number howoften ecore_file_init() was call succesfully;
+ *         0 if it failed.
+ */
+EAPI int
+ecore_file_init()
+{
+   if (++_ecore_file_init_count != 1)
+     return _ecore_file_init_count;
+   _ecore_file_log_dom = eina_log_domain_register("EcoreFile", ECORE_FILE_DEFAULT_LOG_COLOR);
+   if(_ecore_file_log_dom < 0) 
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the ecore file module.");
+       return --_ecore_file_init_count;
+     }
+   ecore_file_path_init();
+   ecore_file_monitor_init();
+   ecore_file_download_init();
+
+   /* FIXME: were the tests disabled for a good reason ? */
+
+   /*
+   if (!ecore_file_monitor_init())
+     goto shutdown_ecore_file_path;
+
+   if (!ecore_file_download_init())
+     goto shutdown_ecore_file_monitor;
+   */
+
+   return _ecore_file_init_count;
+
+   /*
+ shutdown_ecore_file_monitor:
+   ecore_file_monitor_shutdown();
+ shutdown_ecore_file_path:
+   ecore_file_path_shutdown();
+
+   return --_ecore_file_init_count;
+   */
+}
+
+/**
+ * Shutdown the Ecore_File
+ * @return returns the number of libraries that still uses Ecore_File
+ */
+EAPI int
+ecore_file_shutdown()
+{
+   if (--_ecore_file_init_count != 0)
+     return _ecore_file_init_count;
+
+   ecore_file_download_shutdown();
+   ecore_file_monitor_shutdown();
+   ecore_file_path_shutdown();
+   eina_log_domain_unregister(_ecore_file_log_dom);
+   _ecore_file_log_dom = -1;
+   return _ecore_file_init_count;
+}
+
+/**
+ * Get the time of the last modification to the give file
+ * @param file The name of the file
+ * @return Return the time of the last data modification, if an error should
+ *         occur it will return 0
+ */
+EAPI long long
+ecore_file_mod_time(const char *file)
+{
+   struct stat st;
+
+   if (stat(file, &st) < 0) return 0;
+   return st.st_mtime;
+}
+
+/**
+ * Get the size of the given file
+ * @param  file The name of the file
+ * @return The size of the file in byte
+ */
+EAPI long long
+ecore_file_size(const char *file)
+{
+   struct stat st;
+
+   if (stat(file, &st) < 0) return 0;
+   return st.st_size;
+}
+
+/**
+ * Check if file exists
+ * @param  file The name of the file
+ * @return 1 if file exists on local filesystem, 0 otherwise
+ */
+EAPI int
+ecore_file_exists(const char *file)
+{
+   struct stat st;
+
+   /*Workaround so that "/" returns a true, otherwise we can't monitor "/" in ecore_file_monitor*/
+   if (stat(file, &st) < 0 && strcmp(file, "/")) return 0;
+   return 1;
+}
+
+/**
+ * Check if file is a directory
+ * @param  file The name of the file
+ * @return 1 if file exist and is a directory, 0 otherwise
+ */
+EAPI int
+ecore_file_is_dir(const char *file)
+{
+   struct stat st;
+
+   if (stat(file, &st) < 0) return 0;
+   if (S_ISDIR(st.st_mode)) return 1;
+   return 0;
+}
+
+static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+
+/**
+ * Create a new directory
+ * @param  dir The name of the directory to create
+ * @return 1 on successfull creation, 0 on failure
+ *
+ * The directory is created with the mode: S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
+ */
+EAPI int
+ecore_file_mkdir(const char *dir)
+{
+   if (mkdir(dir, default_mode) < 0) return 0;
+   return 1;
+}
+
+/**
+ * Create complete directory in a batch.
+ *
+ * @param dirs list of directories, null terminated.
+ * @return number of successfull directories created, -1 if dirs is NULL.
+ *
+ * @see ecore_file_mkdir() and ecore_file_mkpaths()
+ */
+EAPI int
+ecore_file_mkdirs(const char **dirs)
+{
+   int i = 0;
+
+   if (!dirs) return -1;
+
+   for (; *dirs != NULL; dirs++)
+     if (ecore_file_mkdir(*dirs))
+       i++;
+   return i;
+}
+
+/**
+ * Create complete list of sub-directories in a batch (optimized).
+ *
+ * @param base the base directory to act on, will be created if does
+ *     not exists.
+ * @param subdirs list of directories, null terminated. These are
+ *     created similarly to ecore_file_mkdir(), so same mode and whole
+ *     path to that point must exists. So if creating base/a/b/c,
+ *     provide subdirs with "a", "a/b" and "a/b/c" in that order!
+ *
+ * @return number of successfull directories created, -1 if subdirs or
+ *     base is NULL or invalid.
+ *
+ * @see ecore_file_mkdir() and ecore_file_mkpaths()
+ */
+EAPI int
+ecore_file_mksubdirs(const char *base, const char **subdirs)
+{
+#ifndef HAVE_ATFILE_SOURCE
+   char buf[PATH_MAX];
+   int baselen;
+#else
+   int fd;
+   DIR *dir;
+#endif
+   int i;
+
+   if (!subdirs) return -1;
+   if ((!base) || (base[0] == '\0')) return -1;
+
+   if ((!ecore_file_is_dir(base)) && (!ecore_file_mkpath(base)))
+     return 0;
+
+#ifndef HAVE_ATFILE_SOURCE
+   baselen = eina_strlcpy(buf, base, sizeof(buf));
+   if ((baselen < 1) || (baselen + 1 >= (int)sizeof(buf)))
+     return 0;
+
+   if (buf[baselen - 1] != '/')
+     {
+       buf[baselen] = '/';
+       baselen++;
+     }
+#else
+   dir = opendir(base);
+   if (!dir)
+     return 0;
+   fd = dirfd(dir);
+#endif
+
+   i = 0;
+   for (; *subdirs != NULL; subdirs++)
+     {
+       struct stat st;
+
+#ifndef HAVE_ATFILE_SOURCE
+       eina_strlcpy(buf + baselen, *subdirs, sizeof(buf) - baselen);
+       if (stat(buf, &st) == 0)
+#else
+       if (fstatat(fd, *subdirs, &st, 0) == 0)
+#endif
+         {
+            if (S_ISDIR(st.st_mode))
+              {
+                 i++;
+                 continue;
+              }
+         }
+       else
+         {
+            if (errno == ENOENT)
+              {
+#ifndef HAVE_ATFILE_SOURCE
+                 if (mkdir(buf, default_mode) == 0)
+#else
+                 if (mkdirat(fd, *subdirs, default_mode) == 0)
+#endif
+                   {
+                      i++;
+                      continue;
+                   }
+                }
+           }
+     }
+
+#ifdef HAVE_ATFILE_SOURCE
+   closedir(dir);
+#endif
+
+   return i;
+}
+
+/**
+ * Delete the given dir
+ * @param  dir The name of the directory to delete
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_rmdir(const char *dir)
+{
+   if (rmdir(dir) < 0) return 0;
+   return 1;
+}
+
+/**
+ * Delete the given file
+ * @param  file The name of the file to delete
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_unlink(const char *file)
+{
+   if (unlink(file) < 0) return 0;
+   return 1;
+}
+
+/**
+ * Remove the given file or directory
+ * @param  file The name of the file or directory to delete
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_remove(const char *file)
+{
+   if (remove(file) < 0) return 0;
+   return 1;
+}
+
+/**
+ * Delete a directory and all its contents
+ * @param  dir The name of the directory to delete
+ * @return 1 on success, 0 on failure
+ *
+ * If dir is a link only the link is removed
+ */
+EAPI int
+ecore_file_recursive_rm(const char *dir)
+{
+   DIR *dirp;
+   struct dirent *dp;
+   char path[PATH_MAX], buf[PATH_MAX];
+   struct stat st;
+   int ret;
+
+   if (readlink(dir, buf, sizeof(buf)) > 0)
+     return ecore_file_unlink(dir);
+
+   ret = stat(dir, &st);
+   if ((ret == 0) && (S_ISDIR(st.st_mode)))
+     {
+       ret = 1;
+       if (stat(dir, &st) == -1) return 0;
+       dirp = opendir(dir);
+       if (dirp)
+         {
+            while ((dp = readdir(dirp)))
+              {
+                 if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
+                   {
+                      snprintf(path, PATH_MAX, "%s/%s", dir, dp->d_name);
+                      if (!ecore_file_recursive_rm(path))
+                        ret = 0;
+                   }
+              }
+            closedir(dirp);
+         }
+       if (!ecore_file_rmdir(dir)) ret = 0;
+        return ret;
+     }
+   else
+     {
+       if (ret == -1) return 0;
+       return ecore_file_unlink(dir);
+     }
+}
+
+static inline int
+_ecore_file_mkpath_if_not_exists(const char *path)
+{
+   struct stat st;
+
+   if (stat(path, &st) < 0)
+     return ecore_file_mkdir(path);
+   else if (!S_ISDIR(st.st_mode))
+     return 0;
+   else
+     return 1;
+}
+
+/**
+ * Create a complete path
+ * @param  path The path to create
+ * @return 1 on success, 0 on failure
+ *
+ * @see ecore_file_mkpaths() and ecore_file_mkdir()
+ */
+EAPI int
+ecore_file_mkpath(const char *path)
+{
+   char ss[PATH_MAX];
+   unsigned int i;
+
+   if (ecore_file_is_dir(path))
+     return 1;
+
+   for (i = 0; path[i] != '\0'; ss[i] = path[i], i++)
+     {
+       if (i == sizeof(ss) - 1) return 0;
+       if ((path[i] == '/') && (i > 0))
+         {
+            ss[i] = '\0';
+            if (!_ecore_file_mkpath_if_not_exists(ss))
+              return 0;
+         }
+     }
+   ss[i] = '\0';
+   return _ecore_file_mkpath_if_not_exists(ss);
+}
+
+/**
+ * Create complete paths in a batch.
+ *
+ * @param paths list of paths, null terminated.
+ * @return number of successfull paths created, -1 if paths is NULL.
+ *
+ * @see ecore_file_mkpath() and ecore_file_mkdirs()
+ */
+EAPI int
+ecore_file_mkpaths(const char **paths)
+{
+   int i = 0;
+
+   if (!paths) return -1;
+
+   for (; *paths != NULL; paths++)
+     if (ecore_file_mkpath(*paths))
+       i++;
+   return i;
+}
+
+/**
+ * Copy a file
+ * @param  src The name of the source file
+ * @param  dst The name of the destination file
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_cp(const char *src, const char *dst)
+{
+   FILE *f1, *f2;
+   char buf[16384];
+   char realpath1[PATH_MAX], realpath2[PATH_MAX];
+   size_t num;
+   int ret = 1;
+
+   if (!realpath(src, realpath1)) return 0;
+   if (realpath(dst, realpath2) && !strcmp(realpath1, realpath2)) return 0;
+
+   f1 = fopen(src, "rb");
+   if (!f1) return 0;
+   f2 = fopen(dst, "wb");
+   if (!f2)
+     {
+       fclose(f1);
+       return 0;
+     }
+   while ((num = fread(buf, 1, sizeof(buf), f1)) > 0)
+     {
+       if (fwrite(buf, 1, num, f2) != num) ret = 0;
+     }
+   fclose(f1);
+   fclose(f2);
+   return ret;
+}
+
+/**
+ * Move a file
+ * @param  src The name of the source file
+ * @param  dst The name of the destination file
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_mv(const char *src, const char *dst)
+{
+   char buf[PATH_MAX];
+   int fd;
+
+   if (rename(src, dst))
+     {
+        // File cannot be moved directly because
+        // it resides on a different mount point.
+       if (errno == EXDEV)
+         {
+            struct stat st;
+
+             // Make sure this is a regular file before
+             // we do anything fancy.
+            stat(src, &st);
+            if (S_ISREG(st.st_mode))
+              {
+                 char *dir;
+
+                 dir = ecore_file_dir_get(dst);
+                 // Since we can't directly rename, try to 
+                 // copy to temp file in the dst directory
+                 // and then rename.
+                 snprintf(buf, sizeof(buf), "%s/.%s.tmp.XXXXXX", 
+                          dir, ecore_file_file_get(dst));
+                 free(dir);
+                 fd = mkstemp(buf);
+                 if (fd < 0)
+                   {
+                      perror("mkstemp");
+                      goto FAIL;
+                   }
+                 close(fd);
+
+                 // Copy to temp file
+                 if (!ecore_file_cp(src, buf))
+                   goto FAIL;
+
+                 // Set file permissions of temp file to match src
+                 chmod(buf, st.st_mode);
+
+                 // Try to atomically move temp file to dst
+                 if (rename(buf, dst))
+                   {
+                      // If we still cannot atomically move
+                      // do a normal copy and hope for the best.
+                      if (!ecore_file_cp(buf, dst))
+                        goto FAIL;
+                   }
+
+                 // Delete temporary file and src
+                 ecore_file_unlink(buf);
+                 ecore_file_unlink(src);
+                 goto PASS;
+              }
+         }
+       goto FAIL;
+     }
+
+PASS:
+   return 1;
+
+FAIL:
+   return 0;
+}
+
+/**
+ * Create a symbolic link
+ * @param  src The name of the file to link
+ * @param  dest The name of link
+ * @return 1 on success, 0 on failure
+ */
+EAPI int
+ecore_file_symlink(const char *src, const char *dest)
+{
+   if (!symlink(src, dest)) return 1;
+
+   return 0;
+}
+
+/**
+ * Get the canonicalized absolute pathname
+ * @param  file The file path
+ * @return The canonicalized absolute pathname; on failure it will return
+ *         an empty string
+ */
+EAPI char *
+ecore_file_realpath(const char *file)
+{
+   char buf[PATH_MAX];
+
+   /*
+    * Some implementations of realpath do not conform to the SUS.
+    * And as a result we must prevent a null arg from being passed.
+    */
+   if (!file) return strdup("");
+   if (!realpath(file, buf)) return strdup("");
+
+   return strdup(buf);
+}
+
+/**
+ * Get the filename from a give path
+ * @param  path The complete path
+ * @return Only the file name
+ */
+EAPI const char *
+ecore_file_file_get(const char *path)
+{
+   char *result = NULL;
+
+   if (!path) return NULL;
+   if ((result = strrchr(path, '/'))) result++;
+   else result = (char *)path;
+   return result;
+}
+
+/**
+ * Get the directory where file reside
+ * @param  file The name of the file
+ * @return The directory name
+ */
+EAPI char *
+ecore_file_dir_get(const char *file)
+{
+   char *p;
+   char buf[PATH_MAX];
+
+   if (!file) return NULL;
+   strncpy(buf, file, PATH_MAX);
+   buf[PATH_MAX - 1] = 0;
+   p = dirname(buf);
+   return strdup(p);
+}
+
+/**
+ * Check if file can be read
+ * @param  file The name of the file
+ * @return 1 if the file is readable, 0 otherwise
+ */
+EAPI int
+ecore_file_can_read(const char *file)
+{
+   if (!file) return 0;
+   if (!access(file, R_OK)) return 1;
+   return 0;
+}
+
+/**
+ * Check if file can be written
+ * @param  file The name of the file
+ * @return 1 if the file is writable, 0 otherwise
+ */
+EAPI int
+ecore_file_can_write(const char *file)
+{
+   if (!file) return 0;
+   if (!access(file, W_OK)) return 1;
+   return 0;
+}
+
+/**
+ * Check if file can be executed
+ * @param  file The name of the file
+ * @return 1 if the file can be executed, 0 otherwise
+ */
+EAPI int
+ecore_file_can_exec(const char *file)
+{
+   if (!file) return 0;
+   if (!access(file, X_OK)) return 1;
+   return 0;
+}
+
+/**
+ * Get the path pointed by link
+ * @param  link The name of the link
+ * @return The path pointed by link or NULL
+ */
+EAPI char *
+ecore_file_readlink(const char *link)
+{
+   char buf[PATH_MAX];
+   int count;
+
+   if ((count = readlink(link, buf, sizeof(buf))) < 0) return NULL;
+   buf[count] = 0;
+   return strdup(buf);
+}
+
+/**
+ * Get the list of the files and directories in a given directory. The list
+ * will be sorted with strcoll as compare function. That means that you may
+ * want to set the current locale for the category LC_COLLATE with setlocale().
+ * For more information see the manual pages of strcoll and setlocale.
+ * The list will not contain the directory entries for '.' and '..'.
+ * @param  dir The name of the directory to list
+ * @return Return an Eina_List containing all the files in the directory;
+ *         on failure it returns NULL.
+ */
+EAPI Eina_List *
+ecore_file_ls(const char *dir)
+{
+   char *f;
+   DIR *dirp;
+   struct dirent *dp;
+   Eina_List *list = NULL;
+
+   dirp = opendir(dir);
+   if (!dirp) return NULL;
+
+   while ((dp = readdir(dirp)))
+     {
+       if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
+         {
+              f = strdup(dp->d_name);
+              list = eina_list_append(list, f);
+         }
+     }
+   closedir(dirp);
+
+   list = eina_list_sort(list, eina_list_count(list), EINA_COMPARE_CB(strcoll));
+
+   return list;
+}
+
+/**
+ * FIXME: To be documented.
+ */
+EAPI char *
+ecore_file_app_exe_get(const char *app)
+{
+   char *p, *pp, *exe1 = NULL, *exe2 = NULL;
+   char *exe = NULL;
+   int in_quot_dbl = 0, in_quot_sing = 0, restart = 0;
+
+   if (!app) return NULL;
+
+   p = (char *)app;
+restart:
+   while ((*p) && (isspace(*p))) p++;
+   exe1 = p;
+   while (*p)
+     {
+       if (in_quot_sing)
+         {
+            if (*p == '\'')
+              in_quot_sing = 0;
+         }
+       else if (in_quot_dbl)
+         {
+            if (*p == '\"')
+              in_quot_dbl = 0;
+         }
+       else
+         {
+            if (*p == '\'')
+              in_quot_sing = 1;
+            else if (*p == '\"')
+              in_quot_dbl = 1;
+            if ((isspace(*p)) && (!((p > app) && (p[-1] != '\\'))))
+              break;
+         }
+       p++;
+     }
+   exe2 = p;
+   if (exe2 == exe1) return NULL;
+   if (*exe1 == '~')
+     {
+       char *homedir;
+       int len;
+
+       /* Skip ~ */
+       exe1++;
+
+       homedir = getenv("HOME");
+       if (!homedir) return NULL;
+       len = strlen(homedir);
+       if (exe) free(exe);
+       exe = malloc(len + exe2 - exe1 + 2);
+       if (!exe) return NULL;
+       pp = exe;
+       if (len)
+         {
+            strcpy(exe, homedir);
+            pp += len;
+            if (*(pp - 1) != '/')
+              {
+                 *pp = '/';
+                 pp++;
+              }
+         }
+     }
+   else
+     {
+       if (exe) free(exe);
+       exe = malloc(exe2 - exe1 + 1);
+       if (!exe) return NULL;
+       pp = exe;
+     }
+   p = exe1;
+   restart = 0;
+   in_quot_dbl = 0;
+   in_quot_sing = 0;
+   while (*p)
+     {
+       if (in_quot_sing)
+         {
+            if (*p == '\'')
+              in_quot_sing = 0;
+            else
+              {
+                 *pp = *p;
+                 pp++;
+              }
+         }
+       else if (in_quot_dbl)
+         {
+            if (*p == '\"')
+              in_quot_dbl = 0;
+            else
+              {
+                 /* techcincally this is wrong. double quotes also accept
+                  * special chars:
+                  *
+                  * $, `, \
+                  */
+                 *pp = *p;
+                 pp++;
+              }
+         }
+       else
+         {
+            /* technically we should handle special chars:
+             *
+             * $, `, \, etc.
+             */
+            if ((p > exe1) && (p[-1] == '\\'))
+              {
+                 if (*p != '\n')
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            else if ((p > exe1) && (*p == '='))
+              {
+                 restart = 1;
+                 *pp = *p;
+                 pp++;
+              }
+            else if (*p == '\'')
+              in_quot_sing = 1;
+            else if (*p == '\"')
+              in_quot_dbl = 1;
+            else if (isspace(*p))
+              {
+                 if (restart)
+                   goto restart;
+                 else
+                   break;
+              }
+            else
+              {
+                 *pp = *p;
+                 pp++;
+              }
+         }
+       p++;
+     }
+   *pp = 0;
+   return exe;
+}
+
+/**
+ * Add the escape sequence ('\\') to the given filename
+ * @param  filename The file name
+ * @return The file name with special characters escaped; if the length of the
+ *         resulting string is longer than PATH_MAX it will return NULL
+ */
+EAPI char *
+ecore_file_escape_name(const char *filename)
+{
+   const char *p;
+   char *q;
+   char buf[PATH_MAX];
+
+   p = filename;
+   q = buf;
+   while (*p)
+     {
+       if ((q - buf) > (PATH_MAX - 6)) return NULL;
+       if (
+           (*p == ' ') || (*p == '\t') || (*p == '\n') ||
+           (*p == '\\') || (*p == '\'') || (*p == '\"') ||
+           (*p == ';') || (*p == '!') || (*p == '#') ||
+           (*p == '$') || (*p == '%') || (*p == '&') ||
+           (*p == '*') || (*p == '(') || (*p == ')') ||
+           (*p == '[') || (*p == ']') || (*p == '{') ||
+           (*p == '}') || (*p == '|') || (*p == '<') ||
+           (*p == '>') || (*p == '?')
+           )
+         {
+            *q = '\\';
+            q++;
+         }
+       *q = *p;
+       q++;
+       p++;
+     }
+   *q = 0;
+   return strdup(buf);
+}
+
+/**
+ * Remove the extension from a given path
+ * @param  path The name of the file
+ * @return A newly allocated string with the extension stripped out or NULL on errors
+ */
+EAPI char *
+ecore_file_strip_ext(const char *path)
+{
+   char *p, *file = NULL;
+
+   p = strrchr(path, '.');
+   if (!p)
+     file = strdup(path);
+   else if (p != path)
+     {
+       file = malloc(((p - path) + 1) * sizeof(char));
+       if (file)
+         {
+            memcpy(file, path, (p - path));
+            file[p - path] = 0;
+         }
+     }
+
+   return file;
+}
+
+/**
+ * Check if the given directory is empty. The '.' and '..' files will be ignored.
+ * @param  dir The name of the directory to check
+ * @return 1 if directory is empty, 0 if it has at least one file or -1 in case of errors
+ */
+EAPI int
+ecore_file_dir_is_empty(const char *dir)
+{
+   DIR *dirp;
+   struct dirent *dp;
+
+   dirp = opendir(dir);
+   if (!dirp) return -1;
+
+   while ((dp = readdir(dirp)))
+     {
+       if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
+         {
+            closedir(dirp);
+            return 0;
+         }
+     }
+   
+   closedir(dirp);
+   return 1;
+}
diff --git a/src/lib/ecore_file/ecore_file_download.c b/src/lib/ecore_file/ecore_file_download.c
new file mode 100644 (file)
index 0000000..94682c5
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef BUILD_ECORE_CON
+# include "Ecore_Con.h"
+#endif
+
+#include "ecore_file_private.h"
+
+#ifdef BUILD_ECORE_CON
+
+#define ECORE_MAGIC_FILE_DOWNLOAD_JOB  0xf7427cb8
+
+struct _Ecore_File_Download_Job
+{
+   ECORE_MAGIC;
+
+   Ecore_Con_Url       *url_con;
+   FILE                        *file;
+
+   char                        *dst;
+
+   void        (*completion_cb)(void *data, const char *file, int status);
+
+   int (*progress_cb)  (void *data, const char *file,
+                        long int dltotal, long int dlnow,
+                        long int ultotal, long int ulnow);
+};
+
+#ifdef HAVE_CURL
+Ecore_File_Download_Job *_ecore_file_download_curl(const char *url, const char *dst,
+                                                  void (*completion_cb)(void *data, const char *file, int status),
+                                                  int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow),
+                                                  void *data);
+
+static int _ecore_file_download_url_complete_cb(void *data, int type, void *event);
+static int _ecore_file_download_url_progress_cb(void *data, int type, void *event);
+#endif
+
+static Ecore_Event_Handler     *_url_complete_handler = NULL;
+static Ecore_Event_Handler     *_url_progress_download = NULL;
+static Eina_List               *_job_list;
+
+#endif /* BUILD_ECORE_CON */
+
+int
+ecore_file_download_init(void)
+{
+#ifdef BUILD_ECORE_CON
+  if (!ecore_con_url_init())
+    return 0;
+
+# ifdef HAVE_CURL
+  _url_complete_handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _ecore_file_download_url_complete_cb, NULL);
+  _url_progress_download = ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS, _ecore_file_download_url_progress_cb, NULL);
+# endif
+
+#endif /* BUILD_ECORE_CON */
+
+   return 1;
+}
+
+void
+ecore_file_download_shutdown(void)
+{
+#ifdef BUILD_ECORE_CON
+  if (_url_complete_handler)
+    ecore_event_handler_del(_url_complete_handler);
+  if (_url_progress_download)
+    ecore_event_handler_del(_url_progress_download);
+  _url_complete_handler = NULL;
+  _url_progress_download = NULL;
+  ecore_file_download_abort_all();
+
+  ecore_con_url_shutdown();
+#endif /* BUILD_ECORE_CON */
+}
+
+EAPI void
+ecore_file_download_abort_all(void)
+{
+#ifdef BUILD_ECORE_CON
+   Ecore_File_Download_Job *job;
+
+   EINA_LIST_FREE(_job_list, job)
+            ecore_file_download_abort(job);
+#endif /* BUILD_ECORE_CON */
+}
+
+/**
+ * Download @p url to the given @p dst
+ * @param  url The complete url to download
+ * @param  dst The local file to save the downloaded to
+ * @param  completion_cb A callback called on download complete
+ * @param  progress_cb A callback called during the download operation
+ * @param  data User data passed to both callbacks
+ * @param  job_ret If the protocol in use is http or ftp, this parameter will be
+ * filled with the job. Then you can use ecore_file_download_abort() to cancel it.
+ * 
+ * @return 1 if the download start or 0 on failure
+ *
+ * You must provide the full url, including 'http://', 'ftp://' or 'file://'.\n
+ * If @p dst already exist it will not be overwritten and the function will fail.\n
+ * Ecore must be compiled with CURL to download using http and ftp protocols.\n
+ * The @p status param in the @p completion_cb() will be 0 if the download goes well or
+ * 1 in case of failure.
+ */
+EAPI int
+ecore_file_download(const char *url, const char *dst,
+                   void (*completion_cb)(void *data, const char *file, int status),
+                   int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow),
+                   void *data, Ecore_File_Download_Job **job_ret)
+{
+#ifdef BUILD_ECORE_CON
+   char *dir = ecore_file_dir_get(dst);
+
+   if (!ecore_file_is_dir(dir))
+     {
+       free(dir);
+       return 0;
+     }
+   free(dir);
+   if (ecore_file_exists(dst)) return 0;
+
+   /* FIXME: Add handlers for http and ftp! */
+   if (!strncmp(url, "file://", 7))
+     {
+       /* FIXME: Maybe fork? Might take a while to copy.
+        * Check filesize? */
+       /* Just copy it */
+
+       url += 7;
+       /* skip hostname */
+       url = strchr(url, '/');
+       return ecore_file_cp(url, dst);
+     }
+# ifdef HAVE_CURL
+   else if ((!strncmp(url, "http://", 7)) ||
+           (!strncmp(url, "ftp://", 6)))
+     {
+       /* download */
+       Ecore_File_Download_Job *job;
+
+       job = _ecore_file_download_curl(url, dst, completion_cb, progress_cb, data);
+       if(job_ret) *job_ret = job;
+       return job != NULL;
+     }
+# endif
+   else
+     {
+       return 0;
+     }
+#else
+   completion_cb = NULL;
+   progress_cb = NULL;
+   data = NULL;
+   return 0;
+#endif /* BUILD_ECORE_CON */
+}
+
+/**
+ * Check if the given protocol is available
+ * @param  protocol The protocol to check
+ * @return 1 if protocol is handled or 0 if not
+ *
+ * @p protocol can be 'http://', 'ftp://' or 'file://'.\n
+ * Ecore must be compiled with CURL to handle http and ftp protocols.
+ */
+EAPI int
+ecore_file_download_protocol_available(const char *protocol)
+{
+#ifdef BUILD_ECORE_CON
+   if (!strncmp(protocol, "file://", 7)) return 1;
+# ifdef HAVE_CURL
+   else if (!strncmp(protocol, "http://", 7)) return 1;
+   else if (!strncmp(protocol, "ftp://", 6)) return 1;
+# endif
+#endif /* BUILD_ECORE_CON */
+
+   return 0;
+}
+
+#ifdef BUILD_ECORE_CON
+
+# ifdef HAVE_CURL
+static int
+_ecore_file_download_url_compare_job(const void *data1, const void *data2)
+{
+   const Ecore_File_Download_Job       *job = data1;
+   const Ecore_Con_Url                 *url = data2;
+
+   if (job->url_con == url) return 0;
+   return -1;
+}
+
+static int
+_ecore_file_download_url_complete_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Con_Event_Url_Complete        *ev = event;
+   Ecore_File_Download_Job     *job;
+
+   job = eina_list_search_unsorted(_job_list, _ecore_file_download_url_compare_job, ev->url_con);
+   if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return 1;
+
+
+   if (job->completion_cb)
+     job->completion_cb(ecore_con_url_data_get(job->url_con), job->dst, !ev->status);
+
+   _job_list = eina_list_remove(_job_list, job);
+   fclose(job->file);
+   free(job->dst);
+   free(job);
+
+   return 0;
+}
+
+static int
+_ecore_file_download_url_progress_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+/* this reports the downloads progress. if we return 0, then download
+ * continues, if we return anything else, then the download stops */
+   Ecore_Con_Event_Url_Progress        *ev = event;
+   Ecore_File_Download_Job     *job;
+
+   job = eina_list_search_unsorted(_job_list, _ecore_file_download_url_compare_job, ev->url_con);
+   if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return 1;
+
+   if (job->progress_cb)
+     if (job->progress_cb(ecore_con_url_data_get(job->url_con), job->dst,
+                         (long int) ev->down.total, (long int) ev->down.now,
+                         (long int) ev->up.total, (long int) ev->up.now) != 0)
+       {
+         _job_list = eina_list_remove(_job_list, job);
+         fclose(job->file);
+         free(job->dst);
+         free(job);
+
+         return 1;
+       }
+
+   return 0;
+}
+
+Ecore_File_Download_Job *
+_ecore_file_download_curl(const char *url, const char *dst,
+                         void (*completion_cb)(void *data, const char *file,
+                                               int status),
+                         int (*progress_cb)(void *data, const char *file,
+                                            long int dltotal, long int dlnow,
+                                            long int ultotal, long int ulnow),
+                         void *data)
+{
+   Ecore_File_Download_Job *job;
+
+   job = calloc(1, sizeof(Ecore_File_Download_Job));
+   if (!job) return NULL;
+
+   ECORE_MAGIC_SET(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB);
+
+   job->file = fopen(dst, "wb");
+   if (!job->file)
+     {
+       free(job);
+       return NULL;
+     }
+   job->url_con = ecore_con_url_new(url);
+   if (!job->url_con)
+     {
+       fclose(job->file);
+       free(job);
+       return NULL;
+     }
+
+   ecore_con_url_fd_set(job->url_con, fileno(job->file));
+   ecore_con_url_data_set(job->url_con, data);
+
+   job->dst = strdup(dst);
+
+   job->completion_cb = completion_cb;
+   job->progress_cb = progress_cb;
+   _job_list = eina_list_append(_job_list, job);
+
+   ecore_con_url_send(job->url_con, NULL, 0, NULL);
+
+   return job;
+}
+# endif
+#endif
+
+/**
+ * Abort the given download job
+ * @param  job The download job to abort
+ */
+
+EAPI void
+ecore_file_download_abort(Ecore_File_Download_Job *job)
+{
+#ifdef BUILD_ECORE_CON
+# ifdef HAVE_CURL
+   ecore_con_url_destroy(job->url_con);
+# endif
+   _job_list = eina_list_remove(_job_list, job);
+   fclose(job->file);
+   free(job->dst);
+   free(job);
+#endif /* BUILD_ECORE_CON */
+}
diff --git a/src/lib/ecore_file/ecore_file_monitor.c b/src/lib/ecore_file/ecore_file_monitor.c
new file mode 100644 (file)
index 0000000..72a2496
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_file_private.h"
+
+typedef enum {
+     ECORE_FILE_MONITOR_TYPE_NONE,
+#ifdef HAVE_INOTIFY
+     ECORE_FILE_MONITOR_TYPE_INOTIFY,
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+     ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32,
+#endif
+#ifdef HAVE_POLL
+     ECORE_FILE_MONITOR_TYPE_POLL
+#endif
+} Ecore_File_Monitor_Type;
+
+static Ecore_File_Monitor_Type monitor_type = ECORE_FILE_MONITOR_TYPE_NONE;
+
+int
+ecore_file_monitor_init(void)
+{
+#ifdef HAVE_INOTIFY
+   monitor_type = ECORE_FILE_MONITOR_TYPE_INOTIFY;
+   if (ecore_file_monitor_inotify_init())
+     return 1;
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+   monitor_type = ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32;
+   if (ecore_file_monitor_win32_init())
+     return 1;
+#endif
+#ifdef HAVE_POLL
+   monitor_type = ECORE_FILE_MONITOR_TYPE_POLL;
+   if (ecore_file_monitor_poll_init())
+     return 1;
+#endif
+   monitor_type = ECORE_FILE_MONITOR_TYPE_NONE;
+   return 0;
+}
+
+void
+ecore_file_monitor_shutdown(void)
+{
+   switch (monitor_type)
+     {
+      case ECORE_FILE_MONITOR_TYPE_NONE:
+        break;
+#ifdef HAVE_INOTIFY
+      case ECORE_FILE_MONITOR_TYPE_INOTIFY:
+        ecore_file_monitor_inotify_shutdown();
+        break;
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+      case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
+        ecore_file_monitor_win32_shutdown();
+        break;
+#endif
+#ifdef HAVE_POLL
+      case ECORE_FILE_MONITOR_TYPE_POLL:
+        ecore_file_monitor_poll_shutdown();
+        break;
+#endif
+     }
+}
+
+/**
+ * Monitor a path using inotify or polling
+ * @param  path The path to monitor
+ * @param  func The function to call on changes
+ * @param  data The data passed to func
+ * @return An Ecore_File_Monitor pointer or NULL on failure
+ */
+EAPI Ecore_File_Monitor *
+ecore_file_monitor_add(const char *path,
+                       void      (*func) (void               *data,
+                                          Ecore_File_Monitor *em,
+                                          Ecore_File_Event    event,
+                                          const char         *path),
+                       void       *data)
+{
+   switch (monitor_type)
+     {
+      case ECORE_FILE_MONITOR_TYPE_NONE:
+        return NULL;
+#ifdef HAVE_INOTIFY
+      case ECORE_FILE_MONITOR_TYPE_INOTIFY:
+        return ecore_file_monitor_inotify_add(path, func, data);
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+      case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
+        return ecore_file_monitor_win32_add(path, func, data);
+#endif
+#ifdef HAVE_POLL
+      case ECORE_FILE_MONITOR_TYPE_POLL:
+        return ecore_file_monitor_poll_add(path, func, data);
+#endif
+     }
+   return NULL;
+}
+
+/**
+ * Stop monitoring a path
+ * @param  em The Ecore_File_Monitor to stop
+ */
+EAPI void
+ecore_file_monitor_del(Ecore_File_Monitor *em)
+{
+   switch (monitor_type)
+     {
+      case ECORE_FILE_MONITOR_TYPE_NONE:
+        break;
+#ifdef HAVE_INOTIFY
+      case ECORE_FILE_MONITOR_TYPE_INOTIFY:
+        ecore_file_monitor_inotify_del(em);
+        break;
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+      case ECORE_FILE_MONITOR_TYPE_NOTIFY_WIN32:
+        ecore_file_monitor_win32_del(em);
+        break;
+#endif
+#ifdef HAVE_POLL
+      case ECORE_FILE_MONITOR_TYPE_POLL:
+        ecore_file_monitor_poll_del(em);
+        break;
+#endif
+     }
+}
+
+/**
+ * Get the monitored path
+ * @param  em The Ecore_File_Monitor to query
+ * @return The path that is monitored by @p em
+ */
+EAPI const char *
+ecore_file_monitor_path_get(Ecore_File_Monitor *em)
+{
+   return em->path;
+}
diff --git a/src/lib/ecore_file/ecore_file_monitor_inotify.c b/src/lib/ecore_file/ecore_file_monitor_inotify.c
new file mode 100644 (file)
index 0000000..bc2c111
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ecore_file_private.h"
+
+/*
+ * TODO:
+ *
+ * - Listen to these events:
+ *   IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN
+ * - Read all events first, then call the callbacks. This will prevent several
+ *   callbacks with the typic save cycle (delete file, new file)
+ */
+
+#ifdef HAVE_INOTIFY
+
+#ifdef HAVE_SYS_INOTIFY
+# include <sys/inotify.h>
+#else
+# include <asm/unistd.h>
+# include <linux/inotify.h>
+#endif
+
+#ifndef HAVE_SYS_INOTIFY
+static inline int inotify_init(void);
+static inline int inotify_add_watch(int fd, const char *name, __u32 mask);
+static inline int inotify_rm_watch(int fd, __u32 wd);
+#endif
+
+
+typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
+
+#define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
+
+struct _Ecore_File_Monitor_Inotify
+{
+   Ecore_File_Monitor  monitor;
+   int                 wd;
+};
+
+static Ecore_Fd_Handler *_fdh = NULL;
+static Ecore_File_Monitor    *_monitors = NULL;
+
+static int                 _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
+static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
+static void                _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask);
+static int                 _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path);
+#if 0
+static void                _ecore_file_monitor_inotify_print(char *file, int mask);
+#endif
+
+int
+ecore_file_monitor_inotify_init(void)
+{
+   int fd;
+
+   fd = inotify_init();
+   if (fd < 0)
+     return 0;
+
+   _fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler,
+                                   NULL, NULL, NULL);
+   if (!_fdh)
+     {
+       close(fd);
+       return 0;
+     }
+
+   return 1;
+}
+
+int
+ecore_file_monitor_inotify_shutdown(void)
+{
+   int fd;
+
+   while(_monitors)
+       ecore_file_monitor_inotify_del(_monitors);
+
+   if (_fdh)
+     {
+       fd = ecore_main_fd_handler_fd_get(_fdh);
+       ecore_main_fd_handler_del(_fdh);
+       close(fd);
+     }
+   return 1;
+}
+
+Ecore_File_Monitor *
+ecore_file_monitor_inotify_add(const char *path,
+                              void (*func) (void *data, Ecore_File_Monitor *em,
+                                            Ecore_File_Event event,
+                                            const char *path),
+                              void *data)
+{
+   Ecore_File_Monitor *em;
+   int len;
+
+   em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
+   if (!em) return NULL;
+
+   em->func = func;
+   em->data = data;
+
+   em->path = strdup(path);
+   len = strlen(em->path);
+   if (em->path[len - 1] == '/' && strcmp(em->path, "/"))
+     em->path[len - 1] = 0;
+
+   _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
+
+   if (ecore_file_exists(em->path))
+     {
+       if (!_ecore_file_monitor_inotify_monitor(em, em->path))
+         return NULL;
+     }
+   else
+     {
+       ecore_file_monitor_inotify_del(em);
+       return NULL;
+     }
+
+   return em;
+}
+
+void
+ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
+{
+   int fd;
+
+   _monitors = ECORE_FILE_MONITOR(eina_inlist_remove(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
+
+   fd = ecore_main_fd_handler_fd_get(_fdh);
+   if (ECORE_FILE_MONITOR_INOTIFY(em)->wd)
+     inotify_rm_watch(fd, ECORE_FILE_MONITOR_INOTIFY(em)->wd);
+   free(em->path);
+   free(em);
+}
+
+static int
+_ecore_file_monitor_inotify_handler(void *data __UNUSED__, Ecore_Fd_Handler *fdh)
+{
+   Ecore_File_Monitor *em;
+   char buffer[16384];
+   struct inotify_event *event;
+   int i = 0;
+   int event_size;
+   ssize_t size;
+
+   size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
+   while (i < size)
+     {
+       event = (struct inotify_event *)&buffer[i];
+       event_size = sizeof(struct inotify_event) + event->len;
+       i += event_size;
+
+       em = _ecore_file_monitor_inotify_monitor_find(event->wd);
+       if (!em) continue;
+
+       _ecore_file_monitor_inotify_events(em, (event->len ? event->name : NULL), event->mask);
+     }
+
+   return 1;
+}
+
+static Ecore_File_Monitor *
+_ecore_file_monitor_inotify_monitor_find(int wd)
+{
+   Ecore_File_Monitor *l;
+
+   EINA_INLIST_FOREACH(_monitors, l)
+     {
+       if (ECORE_FILE_MONITOR_INOTIFY(l)->wd == wd)
+         return l;
+     }
+   return NULL;
+}
+
+static void
+_ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask)
+{
+   char buf[PATH_MAX];
+   int isdir;
+
+   if ((file) && (file[0]))
+     snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
+   else
+     strcpy(buf, em->path);
+   isdir = mask & IN_ISDIR;
+
+#if 0
+   _ecore_file_monitor_inotify_print(file, mask);
+#endif
+
+   if (mask & IN_MODIFY)
+     {
+       if (!isdir)
+         em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
+     }
+   if (mask & IN_MOVED_FROM)
+     {
+       if (isdir)
+         em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
+       else
+         em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
+     }
+   if (mask & IN_MOVED_TO)
+     {
+       if (isdir)
+         em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
+       else
+         em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
+     }
+   if (mask & IN_DELETE)
+     {
+       if (isdir)
+         em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
+       else
+         em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
+     }
+   if (mask & IN_CREATE)
+     {
+       if (isdir)
+         em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
+       else
+         em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
+     }
+   if (mask & IN_DELETE_SELF)
+     {
+       em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+     }
+   if (mask & IN_MOVE_SELF)
+     {
+       /* We just call delete. The dir is gone... */
+       em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+     }
+   if (mask & IN_UNMOUNT)
+     {
+       /* We just call delete. The dir is gone... */
+       em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+     }
+   if (mask & IN_IGNORED)
+     {
+       /* The watch is removed. If the file name still exists monitor the new one,
+        * else delete it */
+       if (ecore_file_exists(em->path))
+         {
+            if (!_ecore_file_monitor_inotify_monitor(em, em->path))
+              em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+         }
+       else
+         em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+     }
+}
+
+static int
+_ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path)
+{
+   int mask;
+   mask = IN_MODIFY|
+         IN_MOVED_FROM|IN_MOVED_TO|
+         IN_DELETE|IN_CREATE|
+         IN_DELETE_SELF|IN_MOVE_SELF|
+         IN_UNMOUNT;
+   ECORE_FILE_MONITOR_INOTIFY(em)->wd = inotify_add_watch(ecore_main_fd_handler_fd_get(_fdh),
+                                                         path, mask);
+   if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0)
+     {
+       ERR("inotify_add_watch error");
+       ecore_file_monitor_inotify_del(em);
+       return 0;
+     }
+   return 1;
+}
+
+#ifndef HAVE_SYS_INOTIFY
+static inline int
+inotify_init(void)
+{
+   return syscall(__NR_inotify_init);
+}
+
+static inline int
+inotify_add_watch(int fd, const char *name, __u32 mask)
+{
+   return syscall(__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int
+inotify_rm_watch(int fd, __u32 wd)
+{
+   return syscall(__NR_inotify_rm_watch, fd, wd);
+}
+#endif
+
+#if 0
+static void
+_ecore_file_monitor_inotify_print(char *file, int mask)
+{
+   const char *type;
+
+   if (mask & IN_ISDIR)
+     type = "dir";
+   else
+     type = "file";
+
+   if (mask & IN_MODIFY)
+     {
+       WRN("Inotify modified %s: %s", type, file);
+     }
+   if (mask & IN_MOVED_FROM)
+     {
+       WRN("Inotify moved from %s: %s", type, file);
+     }
+   if (mask & IN_MOVED_TO)
+     {
+       WRN("Inotify moved to %s: %s", type, file);
+     }
+   if (mask & IN_DELETE)
+     {
+       WRN("Inotify delete %s: %s", type, file);
+     }
+   if (mask & IN_CREATE)
+     {
+       WRN("Inotify create %s: %s", type, file);
+     }
+   if (mask & IN_DELETE_SELF)
+     {
+       WRN("Inotify delete self %s: %s", type, file);
+     }
+   if (mask & IN_MOVE_SELF)
+     {
+       WRN("Inotify move self %s: %s", type, file);
+     }
+   if (mask & IN_UNMOUNT)
+     {
+       WRN("Inotify unmount %s: %s", type, file);
+     }
+}
+#endif
+#endif /* HAVE_INOTIFY */
diff --git a/src/lib/ecore_file/ecore_file_monitor_poll.c b/src/lib/ecore_file/ecore_file_monitor_poll.c
new file mode 100644 (file)
index 0000000..07b0a88
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ecore_file_private.h"
+
+#ifdef HAVE_POLL
+
+/*
+ * TODO:
+ * - Implement recursive as an option!
+ * - Keep whole path or just name of file? (Memory or CPU...)
+ * - Remove requests without files?
+ * - Change poll time
+ */
+
+typedef struct _Ecore_File_Monitor_Poll Ecore_File_Monitor_Poll;
+
+#define ECORE_FILE_MONITOR_POLL(x) ((Ecore_File_Monitor_Poll *)(x))
+
+struct _Ecore_File_Monitor_Poll
+{
+   Ecore_File_Monitor  monitor;
+   int                 mtime;
+   unsigned char       deleted;
+};
+
+#define ECORE_FILE_INTERVAL_MIN  1.0
+#define ECORE_FILE_INTERVAL_STEP 0.5
+#define ECORE_FILE_INTERVAL_MAX  5.0
+
+static double         _interval = ECORE_FILE_INTERVAL_MIN;
+static Ecore_Timer   *_timer = NULL;
+static Ecore_File_Monitor *_monitors = NULL;
+static int          _lock = 0;
+
+static int         _ecore_file_monitor_poll_handler(void *data);
+static void        _ecore_file_monitor_poll_check(Ecore_File_Monitor *em);
+static int         _ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name);
+
+int
+ecore_file_monitor_poll_init(void)
+{
+   return 1;
+}
+
+int
+ecore_file_monitor_poll_shutdown(void)
+{
+   while(_monitors)
+       ecore_file_monitor_poll_del(_monitors);
+
+   if (_timer)
+     {
+               ecore_timer_del(_timer);
+       _timer = NULL;
+     }
+   return 1;
+}
+
+Ecore_File_Monitor *
+ecore_file_monitor_poll_add(const char *path,
+                           void (*func) (void *data, Ecore_File_Monitor *em,
+                                         Ecore_File_Event event,
+                                         const char *path),
+                           void *data)
+{
+   Ecore_File_Monitor *em;
+   size_t len;
+
+   if (!path) return NULL;
+   if (!func) return NULL;
+
+   em = calloc(1, sizeof(Ecore_File_Monitor_Poll));
+   if (!em) return NULL;
+
+   if (!_timer)
+     _timer = ecore_timer_add(_interval, _ecore_file_monitor_poll_handler, NULL);
+   else
+     ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN);
+
+   em->path = strdup(path);
+   len = strlen(em->path);
+   if (em->path[len - 1] == '/' && strcmp(em->path, "/"))
+     em->path[len - 1] = 0;
+
+   em->func = func;
+   em->data = data;
+
+   ECORE_FILE_MONITOR_POLL(em)->mtime = ecore_file_mod_time(em->path);
+   if (ecore_file_exists(em->path))
+     {
+       if (ecore_file_is_dir(em->path))
+         {
+            /* Check for subdirs */
+            Eina_List *files;
+            char *file;
+
+            files = ecore_file_ls(em->path);
+            EINA_LIST_FREE(files, file)
+                   {
+                      Ecore_File *f;
+                      char buf[PATH_MAX];
+
+                      f = calloc(1, sizeof(Ecore_File));
+                      if (!f)
+                   {
+                      free(file);
+                        continue;
+                   }
+
+                      snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
+                      f->name = file;
+                      f->mtime = ecore_file_mod_time(buf);
+                      f->is_dir = ecore_file_is_dir(buf);
+                      em->files = (Ecore_File *) eina_inlist_append(EINA_INLIST_GET(em->files), EINA_INLIST_GET(f));
+                   }
+         }
+     }
+   else
+     {
+       ecore_file_monitor_poll_del(em);
+       return NULL;
+     }
+
+   _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
+
+   return em;
+}
+
+void
+ecore_file_monitor_poll_del(Ecore_File_Monitor *em)
+{
+   Ecore_File *l;
+
+   if (_lock)
+     {
+       ECORE_FILE_MONITOR_POLL(em)->deleted = 1;
+       return;
+     }
+
+   /* Remove files */
+   /*It's possible there weren't any files to monitor, so check if the list is init*/
+   if (em->files)
+     {
+       for (l = em->files; l;)
+         {
+            Ecore_File *file = l;
+
+            l = (Ecore_File *) EINA_INLIST_GET(l)->next;
+            free(file->name);
+            free(file);
+         }
+     }
+
+   if (_monitors)
+     _monitors = ECORE_FILE_MONITOR(eina_inlist_remove(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
+
+   free(em->path);
+   free(em);
+
+   if (_timer)
+     {
+       if (!_monitors)
+         {
+            ecore_timer_del(_timer);
+            _timer = NULL;
+         }
+       else
+         ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN);
+     }
+}
+
+static int
+_ecore_file_monitor_poll_handler(void *data __UNUSED__)
+{
+   Ecore_File_Monitor *l;
+
+   _interval += ECORE_FILE_INTERVAL_STEP;
+
+   _lock = 1;
+   EINA_INLIST_FOREACH(_monitors, l)
+       _ecore_file_monitor_poll_check(l);
+   _lock = 0;
+
+   if (_interval > ECORE_FILE_INTERVAL_MAX)
+     _interval = ECORE_FILE_INTERVAL_MAX;
+   ecore_timer_interval_set(_timer, _interval);
+
+   for (l = _monitors; l;)
+     {
+       Ecore_File_Monitor *em = l;
+
+       l = ECORE_FILE_MONITOR(EINA_INLIST_GET(l)->next);
+       if (ECORE_FILE_MONITOR_POLL(em)->deleted)
+         ecore_file_monitor_del(em);
+     }
+   return 1;
+}
+
+static void
+_ecore_file_monitor_poll_check(Ecore_File_Monitor *em)
+{
+   int mtime;
+
+   mtime = ecore_file_mod_time(em->path);
+   if (mtime < ECORE_FILE_MONITOR_POLL(em)->mtime)
+     {
+       Ecore_File *l;
+       Ecore_File_Event event;
+
+       /* Notify all files deleted */
+       for (l = em->files; l;)
+         {
+            Ecore_File *f = l;
+            char buf[PATH_MAX];
+
+            l = (Ecore_File *) EINA_INLIST_GET(l)->next;
+
+            snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
+            if (f->is_dir)
+              event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
+            else
+              event = ECORE_FILE_EVENT_DELETED_FILE;
+            em->func(em->data, em, event, buf);
+            free(f->name);
+            free(f);
+         }
+       em->files = NULL;
+       em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
+       _interval = ECORE_FILE_INTERVAL_MIN;
+     }
+   else
+     {
+       Ecore_File *l;
+
+       /* Check for changed files */
+       for (l = em->files; l;)
+         {
+            Ecore_File *f = l;
+            char buf[PATH_MAX];
+            int mtime;
+            Ecore_File_Event event;
+
+            l = (Ecore_File *) EINA_INLIST_GET(l)->next;
+
+            snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name);
+            mtime = ecore_file_mod_time(buf);
+            if (mtime < f->mtime)
+              {
+                 if (f->is_dir)
+                   event = ECORE_FILE_EVENT_DELETED_DIRECTORY;
+                 else
+                   event = ECORE_FILE_EVENT_DELETED_FILE;
+
+                 em->func(em->data, em, event, buf);
+                 em->files = (Ecore_File *) eina_inlist_remove(EINA_INLIST_GET(em->files), EINA_INLIST_GET(f));
+                 free(f->name);
+                 free(f);
+                 _interval = ECORE_FILE_INTERVAL_MIN;
+              }
+            else if ((mtime > f->mtime) && !(f->is_dir))
+              {
+                 em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
+                 _interval = ECORE_FILE_INTERVAL_MIN;
+                 f->mtime = mtime;
+              }
+            else
+              f->mtime = mtime;
+         }
+
+       /* Check for new files */
+       if (ECORE_FILE_MONITOR_POLL(em)->mtime < mtime)
+         {
+            Eina_List *files;
+            Eina_List *l;
+            char *file;
+
+            /* Files have been added or removed */
+            files = ecore_file_ls(em->path);
+            if (files)
+              {
+                 /* Are we a directory? We should check first, rather than rely on null here*/
+                 EINA_LIST_FOREACH(files, l, file)
+                   {
+                      Ecore_File *f;
+                      char buf[PATH_MAX];
+                      Ecore_File_Event event;
+
+                      if (_ecore_file_monitor_poll_checking(em, file))
+                        continue;
+
+                      snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
+                      f = calloc(1, sizeof(Ecore_File));
+                      if (!f)
+                        continue;
+
+                      f->name = strdup(file);
+                      f->mtime = ecore_file_mod_time(buf);
+                      f->is_dir = ecore_file_mod_time(buf);
+                      if (f->is_dir)
+                        event = ECORE_FILE_EVENT_CREATED_DIRECTORY;
+                      else
+                        event = ECORE_FILE_EVENT_CREATED_FILE;
+                      em->func(em->data, em, event, buf);
+                      em->files = (Ecore_File *) eina_inlist_append(EINA_INLIST_GET(em->files), EINA_INLIST_GET(f));
+                   }
+                 while (files)
+                   {
+                      file = eina_list_data_get(files);
+                      free(file);
+                      files = eina_list_remove_list(files, files);
+                   }
+              }
+
+            if (!ecore_file_is_dir(em->path))
+              em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, em->path);
+            _interval = ECORE_FILE_INTERVAL_MIN;
+         }
+     }
+   ECORE_FILE_MONITOR_POLL(em)->mtime = mtime;
+}
+
+static int
+_ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name)
+{
+   Ecore_File *l;
+
+   EINA_INLIST_FOREACH(em->files, l)
+     {
+       if (!strcmp(l->name, name))
+         return 1;
+     }
+   return 0;
+}
+#endif
diff --git a/src/lib/ecore_file/ecore_file_monitor_win32.c b/src/lib/ecore_file/ecore_file_monitor_win32.c
new file mode 100644 (file)
index 0000000..c9992c5
--- /dev/null
@@ -0,0 +1,310 @@
+/*\r
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2\r
+ */\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif\r
+\r
+#ifdef HAVE_NOTIFY_WIN32\r
+\r
+# define WIN32_LEAN_AND_MEAN\r
+# include <windows.h>\r
+# undef WIN32_LEAN_AND_MEAN\r
+# include <process.h>\r
+\r
+# include "ecore_file_private.h"\r
+\r
+\r
+typedef struct _Ecore_File_Monitor_Win32      Ecore_File_Monitor_Win32;\r
+typedef struct _Ecore_File_Monitor_Win32_Data Ecore_File_Monitor_Win32_Data;\r
+\r
+/* 4096 = 256 * sizeof(FILE_NOTIFY_INFORMATION) */\r
+# define ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE 4096\r
+# define ECORE_FILE_MONITOR_WIN32(x) ((Ecore_File_Monitor_Win32 *)(x))\r
+\r
+struct _Ecore_File_Monitor_Win32_Data\r
+{\r
+   char                 buffer[ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE];\r
+   OVERLAPPED           overlapped;\r
+   HANDLE               handle;\r
+   HANDLE               event;\r
+   Ecore_File_Monitor  *monitor;\r
+   Ecore_Win32_Handler *h;\r
+   DWORD                buf_length;\r
+   int                  is_dir;\r
+};\r
+\r
+struct _Ecore_File_Monitor_Win32\r
+{\r
+   Ecore_File_Monitor             monitor;\r
+   Ecore_File_Monitor_Win32_Data *file;\r
+   Ecore_File_Monitor_Win32_Data *dir;\r
+};\r
+\r
+static Ecore_File_Monitor *_monitors = NULL;\r
+\r
+static int _ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh);\r
+\r
+\r
+static Ecore_File_Monitor_Win32_Data *\r
+_ecore_file_monitor_win32_data_new(Ecore_File_Monitor *monitor, int type)\r
+{\r
+   Ecore_File_Monitor_Win32_Data *md;\r
+   DWORD                          filter;\r
+\r
+   md = (Ecore_File_Monitor_Win32_Data *)calloc(1, sizeof(Ecore_File_Monitor_Win32_Data));\r
+   if (!md) return NULL;\r
+\r
+   md->handle = CreateFile(monitor->path,\r
+                           FILE_LIST_DIRECTORY,\r
+                           FILE_SHARE_READ |\r
+                           FILE_SHARE_WRITE,\r
+                           NULL,\r
+                           OPEN_EXISTING,\r
+                           FILE_FLAG_BACKUP_SEMANTICS |\r
+                           FILE_FLAG_OVERLAPPED,\r
+                           NULL);\r
+   if (md->handle == INVALID_HANDLE_VALUE)\r
+     goto free_md;\r
+\r
+   md->event = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+   if (!md->event)\r
+     goto close_handle;\r
+\r
+   ZeroMemory (&md->overlapped, sizeof(md->overlapped));\r
+   md->overlapped.hEvent = md->event;\r
+\r
+   filter = (type == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;\r
+   filter |=\r
+     FILE_NOTIFY_CHANGE_ATTRIBUTES |\r
+     FILE_NOTIFY_CHANGE_SIZE |\r
+     FILE_NOTIFY_CHANGE_LAST_WRITE |\r
+     FILE_NOTIFY_CHANGE_LAST_ACCESS |\r
+     FILE_NOTIFY_CHANGE_CREATION |\r
+     FILE_NOTIFY_CHANGE_SECURITY;\r
+\r
+   if (!ReadDirectoryChangesW(md->handle,\r
+                              md->buffer,\r
+                              ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE,\r
+                              FALSE,\r
+                              filter,\r
+                              &md->buf_length,\r
+                              &md->overlapped,\r
+                              NULL))\r
+     goto close_event;\r
+\r
+   md->h = ecore_main_win32_handler_add(md->event,\r
+                                        _ecore_file_monitor_win32_cb,\r
+                                        md);\r
+   if (!md->h)\r
+     goto close_event;\r
+\r
+   md->monitor = monitor;\r
+   md->is_dir = type;\r
+\r
+   return md;\r
+\r
+ close_event:\r
+   CloseHandle(md->event);\r
+ close_handle:\r
+   CloseHandle(md->handle);\r
+ free_md:\r
+   free(md);\r
+\r
+   return NULL;\r
+}\r
+\r
+static void\r
+_ecore_file_monitor_win32_data_free(Ecore_File_Monitor_Win32_Data *md)\r
+{\r
+   if (!md) return;\r
+\r
+   CloseHandle(md->event);\r
+   CloseHandle (md->handle);\r
+   free (md);\r
+}\r
+\r
+static int\r
+_ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh)\r
+{\r
+   char                           filename[PATH_MAX];\r
+   PFILE_NOTIFY_INFORMATION       fni;\r
+   Ecore_File_Monitor_Win32_Data *md;\r
+   wchar_t                       *wname;\r
+   char                          *name;\r
+   DWORD                          filter;\r
+   DWORD                          offset;\r
+   DWORD                          buf_length;\r
+   Ecore_File_Event               event = ECORE_FILE_EVENT_NONE;\r
+\r
+   md = (Ecore_File_Monitor_Win32_Data *)data;\r
+\r
+   if (!GetOverlappedResult (md->handle, &md->overlapped, &buf_length, TRUE))\r
+     return 1;\r
+\r
+   fni = (PFILE_NOTIFY_INFORMATION)md->buffer;\r
+   do {\r
+      if (!fni)\r
+        break;\r
+      offset = fni->NextEntryOffset;\r
+\r
+      wname = (wchar_t *)malloc(sizeof(wchar_t) * (fni->FileNameLength + 1));\r
+      if (!wname)\r
+        return 0;\r
+\r
+      memcpy(wname, fni->FileName, fni->FileNameLength);\r
+      wname[fni->FileNameLength]='\0';\r
+      name = evil_wchar_to_char(wname);\r
+      free(wname);\r
+      if (!name)\r
+        return 0;\r
+\r
+      _snprintf(filename, PATH_MAX, "%s\\%s", md->monitor->path, name);\r
+      free(name);\r
+\r
+      switch (fni->Action)\r
+        {\r
+        case FILE_ACTION_ADDED:\r
+          if (md->is_dir)\r
+            event = ECORE_FILE_EVENT_CREATED_DIRECTORY;\r
+          else\r
+            event = ECORE_FILE_EVENT_CREATED_FILE;\r
+          break;\r
+        case FILE_ACTION_REMOVED:\r
+          if (md->is_dir)\r
+            event = ECORE_FILE_EVENT_DELETED_DIRECTORY;\r
+          else\r
+            event = ECORE_FILE_EVENT_DELETED_FILE;\r
+          break;\r
+        case FILE_ACTION_MODIFIED:\r
+          if (!md->is_dir)\r
+            event = ECORE_FILE_EVENT_MODIFIED;\r
+          break;\r
+        case FILE_ACTION_RENAMED_OLD_NAME:\r
+          if (md->is_dir)\r
+            event = ECORE_FILE_EVENT_DELETED_DIRECTORY;\r
+          else\r
+            event = ECORE_FILE_EVENT_DELETED_FILE;\r
+          break;\r
+        case FILE_ACTION_RENAMED_NEW_NAME:\r
+          if (md->is_dir)\r
+            event = ECORE_FILE_EVENT_CREATED_DIRECTORY;\r
+          else\r
+            event = ECORE_FILE_EVENT_CREATED_FILE;\r
+          break;\r
+        default: \r
+          fprintf(stderr, "unknown event\n");\r
+          event = ECORE_FILE_EVENT_NONE;\r
+          break;\r
+        }\r
+      if (event != ECORE_FILE_EVENT_NONE)\r
+        md->monitor->func(md->monitor->data, md->monitor, event, filename);\r
+\r
+      fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset);\r
+   } while (offset);\r
+\r
+   filter = (md->is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;\r
+   filter |=\r
+     FILE_NOTIFY_CHANGE_ATTRIBUTES |\r
+     FILE_NOTIFY_CHANGE_SIZE |\r
+     FILE_NOTIFY_CHANGE_LAST_WRITE |\r
+     FILE_NOTIFY_CHANGE_LAST_ACCESS |\r
+     FILE_NOTIFY_CHANGE_CREATION |\r
+     FILE_NOTIFY_CHANGE_SECURITY;\r
+\r
+    ReadDirectoryChangesW(md->handle,\r
+                          md->buffer,\r
+                          ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE,\r
+                          FALSE,\r
+                          filter,\r
+                          &md->buf_length,\r
+                          &md->overlapped,\r
+                          NULL);\r
+   return 1;\r
+}\r
+\r
+int\r
+ecore_file_monitor_win32_init(void)\r
+{\r
+   return 1;\r
+}\r
+\r
+int\r
+ecore_file_monitor_win32_shutdown(void)\r
+{\r
+   return 1;\r
+}\r
+\r
+Ecore_File_Monitor *\r
+ecore_file_monitor_win32_add(const char *path,\r
+                             void (*func) (void *data, Ecore_File_Monitor *em,\r
+                                           Ecore_File_Event event,\r
+                                           const char *path),\r
+                             void *data)\r
+{\r
+   Ecore_File_Monitor_Win32 *m;\r
+   Ecore_File_Monitor       *em;\r
+   size_t                    len;\r
+\r
+   if (!path || (*path == '\0')) return NULL;\r
+   if (!ecore_file_exists(path) || !ecore_file_is_dir(path))\r
+     return NULL;\r
+   if (!func) return NULL;\r
+\r
+   em = (Ecore_File_Monitor *)calloc(1, sizeof(Ecore_File_Monitor_Win32));\r
+   if (!em) return NULL;\r
+\r
+   em->func = func;\r
+   em->data = data;\r
+\r
+   em->path = strdup(path);\r
+   if (!em->path)\r
+     {\r
+        free(em);\r
+        return NULL;\r
+     }\r
+   len = strlen(em->path);\r
+   if (em->path[len - 1] == '/' || em->path[len - 1] == '\\')\r
+     em->path[len - 1] = '\0';\r
+\r
+   m = ECORE_FILE_MONITOR_WIN32(em);\r
+\r
+   m->file = _ecore_file_monitor_win32_data_new(em, 0);\r
+   if (!m->file)\r
+     {\r
+        free(em->path);\r
+        free(em);\r
+        return NULL;\r
+     }\r
+\r
+   m->dir = _ecore_file_monitor_win32_data_new(em, 1);\r
+   if (!m->dir)\r
+     {\r
+        _ecore_file_monitor_win32_data_free(m->file);\r
+        free(em->path);\r
+        free(em);\r
+        return NULL;\r
+     }\r
+\r
+   _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));\r
+\r
+   return em;\r
+}\r
+\r
+void\r
+ecore_file_monitor_win32_del(Ecore_File_Monitor *em)\r
+{\r
+   Ecore_File_Monitor_Win32 *m;\r
+\r
+   if (!em)\r
+     return;\r
+\r
+   m = ECORE_FILE_MONITOR_WIN32(em);\r
+   _ecore_file_monitor_win32_data_free(m->dir);\r
+   _ecore_file_monitor_win32_data_free(m->file);\r
+   free(em->path);\r
+   free(em);\r
+}\r
+\r
+#endif\r
diff --git a/src/lib/ecore_file/ecore_file_path.c b/src/lib/ecore_file/ecore_file_path.c
new file mode 100644 (file)
index 0000000..2e66074
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ecore_file_private.h"
+
+static Eina_List *__ecore_file_path_bin = NULL;
+
+static Eina_List *_ecore_file_path_from_env(const char *env);
+
+void
+ecore_file_path_init(void)
+{
+   __ecore_file_path_bin = _ecore_file_path_from_env("PATH");
+}
+
+void
+ecore_file_path_shutdown(void)
+{
+   char *dir;
+
+   EINA_LIST_FREE(__ecore_file_path_bin, dir)
+     free(dir);
+}
+
+Eina_List *
+_ecore_file_path_from_env(const char *env)
+{
+   Eina_List *path = NULL;
+   char *env_path, *p, *last;
+
+   env_path = getenv(env);
+   if (!env_path)
+     return path;
+
+   env_path = strdup(env_path);
+   last = env_path;
+   for (p = env_path; *p; p++)
+     {
+        if (*p == ':')
+          *p = '\0';
+
+        if (!*p)
+          {
+            if (!ecore_file_path_dir_exists(last))
+              path = eina_list_append(path, strdup(last));
+             last = p + 1;
+          }
+     }
+   if (p > last)
+     path = eina_list_append(path, strdup(last));
+
+   free(env_path);
+   return path;
+}
+
+/**
+ * Check if the given directory is in PATH
+ * @param The name of the directory to search in PATH
+ * @return 1 if the directory exist in PATH, 0 otherwise
+ */
+EAPI int
+ecore_file_path_dir_exists(const char *in_dir)
+{
+   Eina_List *l;
+   char *dir;
+
+   if (!__ecore_file_path_bin) return 0;
+   EINA_LIST_FOREACH(__ecore_file_path_bin, l, dir)
+     {
+       if (strcmp(dir, in_dir))
+         return 1;
+     }
+
+   return 0;
+}
+
+/**
+ * Check if the given application is installed
+ * @param  exe The name of the application
+ * @return 1 if the exe is in PATH and is executable
+ * 
+ * This function check if the given name exist in PATH and is executable 
+ */
+EAPI int
+ecore_file_app_installed(const char *exe)
+{
+   Eina_List *l;
+   char *dir;
+   char  buf[PATH_MAX];
+
+   if (!exe) return 0;
+   if (ecore_file_can_exec(exe)) return 1;
+
+   EINA_LIST_FOREACH(__ecore_file_path_bin, l, dir)
+     {
+       snprintf(buf, sizeof(buf), "%s/%s", dir, exe);
+       if (ecore_file_can_exec(buf))
+         return 1;
+     }
+
+   return 0;
+}
+
+/**
+ * Get a list of all the applications installed on the system
+ * @return An Eina_List containing all the executable files in the system
+ */
+EAPI Eina_List *
+ecore_file_app_list(void)
+{
+   Eina_List *list = NULL;
+   Eina_List *files;
+   Eina_List *l;
+   char  buf[PATH_MAX], *dir, *exe;
+   
+   EINA_LIST_FOREACH(__ecore_file_path_bin, l, dir)
+     {
+       files = ecore_file_ls(dir);
+       EINA_LIST_FREE(files, exe)
+              {
+                 snprintf(buf, sizeof(buf), "%s/%s", dir, exe);
+                 if ((ecore_file_can_exec(buf)) &&
+                     (!ecore_file_is_dir(buf)))
+              list = eina_list_append(list, strdup(buf));
+            free(exe);
+         }
+     }
+
+   return list;
+}
diff --git a/src/lib/ecore_file/ecore_file_private.h b/src/lib/ecore_file/ecore_file_private.h
new file mode 100644 (file)
index 0000000..0729872
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef ECORE_FILE_PRIVATE_H_
+#define ECORE_FILE_PRIVATE_H_
+
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS  64
+#endif
+
+#ifdef __linux__
+# include <features.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#include "Ecore_File.h"
+
+extern int _ecore_file_log_dom;
+
+#ifdef ECORE_FILE_DEFAULT_LOG_COLOR
+#undef ECORE_FILE_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_FILE_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_file_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_file_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_file_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_file_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_file_log_dom, __VA_ARGS__)
+
+/* ecore_file_monitor */
+int  ecore_file_monitor_init(void);
+void ecore_file_monitor_shutdown(void);
+
+#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x))
+
+typedef struct _Ecore_File Ecore_File;
+struct _Ecore_File
+{
+   EINA_INLIST;
+   char          *name;
+   int            mtime;
+   unsigned char  is_dir;
+};
+
+struct _Ecore_File_Monitor
+{
+   EINA_INLIST;
+   void (*func) (void *data,
+                Ecore_File_Monitor *ecore_file_monitor,
+                Ecore_File_Event event,
+                const char *path);
+
+   char               *path;
+   void               *data;
+   Ecore_File         *files;
+};
+
+#ifdef HAVE_INOTIFY
+int                 ecore_file_monitor_inotify_init(void);
+int                 ecore_file_monitor_inotify_shutdown(void);
+Ecore_File_Monitor *ecore_file_monitor_inotify_add(const char *path,
+                                                       void (*func) (void *data,
+                                                                     Ecore_File_Monitor *ecore_file_monitor,
+                                                                     Ecore_File_Event event,
+                                                                     const char *path),
+                                                       void *data);
+void                ecore_file_monitor_inotify_del(Ecore_File_Monitor *ecore_file_monitor);
+#endif
+#ifdef HAVE_NOTIFY_WIN32
+int                 ecore_file_monitor_win32_init(void);
+int                 ecore_file_monitor_win32_shutdown(void);
+Ecore_File_Monitor *ecore_file_monitor_win32_add(const char *path,
+                                                 void      (*func) (void               *data,
+                                                                    Ecore_File_Monitor *ecore_file_monitor,
+                                                                    Ecore_File_Event    event,
+                                                                    const char         *path),
+                                                 void       *data);
+void                ecore_file_monitor_win32_del(Ecore_File_Monitor *ecore_file_monitor);
+#endif
+
+#ifdef HAVE_POLL
+int                 ecore_file_monitor_poll_init(void);
+int                 ecore_file_monitor_poll_shutdown(void);
+Ecore_File_Monitor *ecore_file_monitor_poll_add(const char *path,
+                                               void (*func) (void *data,
+                                                             Ecore_File_Monitor *ecore_file_monitor,
+                                                             Ecore_File_Event event,
+                                                             const char *path),
+                                               void *data);
+void                ecore_file_monitor_poll_del(Ecore_File_Monitor *ecore_file_monitor);
+
+#endif
+
+/* ecore_file_path */
+void ecore_file_path_init(void);
+void ecore_file_path_shutdown(void);
+
+/* ecore_file_download */
+int  ecore_file_download_init(void);
+void ecore_file_download_shutdown(void);
+
+#endif
diff --git a/src/lib/ecore_imf/.cvsignore b/src/lib/ecore_imf/.cvsignore
new file mode 100644 (file)
index 0000000..09980ae
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/ecore_imf/Ecore_IMF.h b/src/lib/ecore_imf/Ecore_IMF.h
new file mode 100644 (file)
index 0000000..d75a521
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_IMF_H
+#define _ECORE_IMF_H
+
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_IMF_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_IMF_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   /* Events sent by the Input Method */
+   typedef struct _Ecore_IMF_Event_Preedit_Start      Ecore_IMF_Event_Preedit_Start;
+   typedef struct _Ecore_IMF_Event_Preedit_End        Ecore_IMF_Event_Preedit_End;
+   typedef struct _Ecore_IMF_Event_Preedit_Changed    Ecore_IMF_Event_Preedit_Changed;
+   typedef struct _Ecore_IMF_Event_Commit             Ecore_IMF_Event_Commit;
+   typedef struct _Ecore_IMF_Event_Delete_Surrounding Ecore_IMF_Event_Delete_Surrounding;
+
+   /* Events to filter */
+   typedef struct _Ecore_IMF_Event_Mouse_Down         Ecore_IMF_Event_Mouse_Down;
+   typedef struct _Ecore_IMF_Event_Mouse_Up           Ecore_IMF_Event_Mouse_Up;
+   typedef struct _Ecore_IMF_Event_Mouse_In           Ecore_IMF_Event_Mouse_In;
+   typedef struct _Ecore_IMF_Event_Mouse_Out          Ecore_IMF_Event_Mouse_Out;
+   typedef struct _Ecore_IMF_Event_Mouse_Move         Ecore_IMF_Event_Mouse_Move;
+   typedef struct _Ecore_IMF_Event_Mouse_Wheel        Ecore_IMF_Event_Mouse_Wheel;
+   typedef struct _Ecore_IMF_Event_Key_Down           Ecore_IMF_Event_Key_Down;
+   typedef struct _Ecore_IMF_Event_Key_Up             Ecore_IMF_Event_Key_Up;
+   typedef union  _Ecore_IMF_Event                    Ecore_IMF_Event;
+
+   typedef struct _Ecore_IMF_Context                  Ecore_IMF_Context;                  /**< An Input Method Context */
+   typedef struct _Ecore_IMF_Context_Class            Ecore_IMF_Context_Class;            /**< An Input Method Context class */
+   typedef struct _Ecore_IMF_Context_Info             Ecore_IMF_Context_Info;             /**< An Input Method Context info */
+
+   EAPI extern int ECORE_IMF_EVENT_PREEDIT_START;
+   EAPI extern int ECORE_IMF_EVENT_PREEDIT_END;
+   EAPI extern int ECORE_IMF_EVENT_PREEDIT_CHANGED;
+   EAPI extern int ECORE_IMF_EVENT_COMMIT;
+   EAPI extern int ECORE_IMF_EVENT_DELETE_SURROUNDING;
+
+   typedef enum
+     {
+       ECORE_IMF_EVENT_MOUSE_DOWN,
+       ECORE_IMF_EVENT_MOUSE_UP,
+       ECORE_IMF_EVENT_MOUSE_IN,
+       ECORE_IMF_EVENT_MOUSE_OUT,
+       ECORE_IMF_EVENT_MOUSE_MOVE,
+       ECORE_IMF_EVENT_MOUSE_WHEEL,
+       ECORE_IMF_EVENT_KEY_DOWN,
+       ECORE_IMF_EVENT_KEY_UP
+     } Ecore_IMF_Event_Type;
+
+   typedef enum
+     {
+       ECORE_IMF_KEYBOARD_MODIFIER_NONE  = 0,      /**< No active modifiers */
+       ECORE_IMF_KEYBOARD_MODIFIER_CTRL  = 1 << 0, /**< "Control" is pressed */
+       ECORE_IMF_KEYBOARD_MODIFIER_ALT   = 1 << 1, /**< "Alt" is pressed */
+       ECORE_IMF_KEYBOARD_MODIFIER_SHIFT = 1 << 2, /**< "Shift" is pressed */
+       ECORE_IMF_KEYBOARD_MODIFIER_WIN   = 1 << 3  /**< "Win" (between "Ctrl" and "Alt") is pressed */
+     } Ecore_IMF_Keyboard_Modifiers;
+
+   typedef enum
+     {
+       ECORE_IMF_KEYBOARD_LOCK_NONE      = 0,      /**< No locks are active */
+       ECORE_IMF_KEYBOARD_LOCK_NUM       = 1 << 0, /**< "Num" lock is active */
+       ECORE_IMF_KEYBOARD_LOCK_CAPS      = 1 << 1, /**< "Caps" lock is active */
+       ECORE_IMF_KEYBOARD_LOCK_SCROLL    = 1 << 2  /**< "Scroll" lock is active */
+     } Ecore_IMF_Keyboard_Locks;
+
+   typedef enum
+     {
+       ECORE_IMF_MOUSE_NONE              = 0,      /**< A single click */
+       ECORE_IMF_MOUSE_DOUBLE_CLICK      = 1 << 0, /**< A double click */
+       ECORE_IMF_MOUSE_TRIPLE_CLICK      = 1 << 1  /**< A triple click */
+     } Ecore_IMF_Mouse_Flags;
+
+   typedef enum
+     {
+       ECORE_IMF_INPUT_MODE_ALPHA        = 1 << 0,
+       ECORE_IMF_INPUT_MODE_NUMERIC      = 1 << 1,
+       ECORE_IMF_INPUT_MODE_SPECIAL      = 1 << 2,
+       ECORE_IMF_INPUT_MODE_HEXA         = 1 << 3,
+       ECORE_IMF_INPUT_MODE_TELE         = 1 << 4,
+       ECORE_IMF_INPUT_MODE_FULL         = (ECORE_IMF_INPUT_MODE_ALPHA | ECORE_IMF_INPUT_MODE_NUMERIC | ECORE_IMF_INPUT_MODE_SPECIAL),
+       ECORE_IMF_INPUT_MODE_INVISIBLE    = 1 << 29,
+       ECORE_IMF_INPUT_MODE_AUTOCAP      = 1 << 30
+     } Ecore_IMF_Input_Mode;
+
+   struct _Ecore_IMF_Event_Preedit_Start
+     {
+       Ecore_IMF_Context *ctx;
+     };
+
+   struct _Ecore_IMF_Event_Preedit_End
+     {
+       Ecore_IMF_Context *ctx;
+     };
+
+   struct _Ecore_IMF_Event_Preedit_Changed
+     {
+       Ecore_IMF_Context *ctx;
+     };
+
+   struct _Ecore_IMF_Event_Commit
+     {
+       Ecore_IMF_Context *ctx;
+       char *str;
+     };
+
+   struct _Ecore_IMF_Event_Delete_Surrounding
+     {
+       Ecore_IMF_Context *ctx;
+       int offset;
+       int n_chars;
+     };
+
+   struct _Ecore_IMF_Event_Mouse_Down
+     {
+       int button;                             /**< The button which has been pressed */
+       struct {
+            int x, y;
+       } output;
+       struct {
+            int x, y;
+       } canvas;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       Ecore_IMF_Mouse_Flags        flags;     /**< The flags corresponding the mouse click (single, double or triple click) */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Mouse_Up
+     {
+       int button;                             /**< The button which has been pressed */
+       struct {
+            int x, y;
+       } output;
+       struct {
+            int x, y;
+       } canvas;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       Ecore_IMF_Mouse_Flags        flags;     /**< The flags corresponding the mouse click (single, double or triple click) */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Mouse_In
+     {
+       int buttons;
+       struct {
+            int x, y;
+       } output;
+       struct {
+            int x, y;
+       } canvas;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Mouse_Out
+     {
+       int buttons;
+       struct {
+            int x, y;
+       } output;
+       struct {
+            int x, y;
+       } canvas;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Mouse_Move
+     {
+       int buttons;
+       struct {
+            struct {
+                 int x, y;
+            } output;
+            struct {
+                 int x, y;
+            } canvas;
+       } cur, prev;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Mouse_Wheel
+     {
+       int direction;                         /* 0 = default up/down wheel */
+       int z;                                 /* ...,-2,-1 = down, 1,2,... = up */
+       struct {
+            int x, y;
+       } output;
+       struct {
+            int x, y;
+       } canvas;
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   struct _Ecore_IMF_Event_Key_Down
+     {
+       const char                  *keyname;   /**< The string name of the key pressed */
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       const char                  *key;       /**< The logical key : (eg shift+1 == exclamation) */
+       const char                  *string;    /**< A UTF8 string if this keystroke has produced a visible string to be ADDED */
+       const char                  *compose;   /**< A UTF8 string if this keystroke has modified a string in the middle of being composed - this string replaces the previous one */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+   };
+
+   struct _Ecore_IMF_Event_Key_Up
+     {
+       const char                  *keyname;   /**< The string name of the key pressed */
+       Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
+       Ecore_IMF_Keyboard_Locks     locks;     /**< The keyboard locks active when the event has been emitted */
+       const char                  *key;       /**< The logical key : (eg shift+1 == exclamation) */
+       const char                  *string;    /**< A UTF8 string if this keystroke has produced a visible string to be ADDED */
+       const char                  *compose;   /**< A UTF8 string if this keystroke has modified a string in the middle of being composed - this string replaces the previous one */
+       unsigned int                 timestamp; /**< The timestamp when the event occured */
+     };
+
+   union _Ecore_IMF_Event
+     {
+       Ecore_IMF_Event_Mouse_Down mouse_down;
+       Ecore_IMF_Event_Mouse_Up mouse_up;
+       Ecore_IMF_Event_Mouse_In mouse_in;
+       Ecore_IMF_Event_Mouse_Out mouse_out;
+       Ecore_IMF_Event_Mouse_Move mouse_move;
+       Ecore_IMF_Event_Mouse_Wheel mouse_wheel;
+       Ecore_IMF_Event_Key_Down key_down;
+       Ecore_IMF_Event_Key_Up key_up;
+     };
+
+   struct _Ecore_IMF_Context_Class
+     {
+       void (*add)                 (Ecore_IMF_Context *ctx);
+       void (*del)                 (Ecore_IMF_Context *ctx);
+       void (*client_window_set)   (Ecore_IMF_Context *ctx, void *window);
+       void (*client_canvas_set)   (Ecore_IMF_Context *ctx, void *canvas);
+       void (*show)                (Ecore_IMF_Context *ctx);
+       void (*hide)                (Ecore_IMF_Context *ctx);
+       void (*preedit_string_get)  (Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
+       void (*focus_in)            (Ecore_IMF_Context *ctx);
+       void (*focus_out)           (Ecore_IMF_Context *ctx);
+       void (*reset)               (Ecore_IMF_Context *ctx);
+       void (*cursor_position_set) (Ecore_IMF_Context *ctx, int cursor_pos);
+       void (*use_preedit_set)     (Ecore_IMF_Context *ctx, int use_preedit);
+       void (*input_mode_set)      (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
+       int  (*filter_event)        (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
+     };
+
+   struct _Ecore_IMF_Context_Info
+     {
+       const char *id;              /* ID */
+       const char *description;     /* Human readable description */
+       const char *default_locales; /* Languages for which this context is the default, separated by : */
+       const char *canvas_type;     /* The canvas type used by the input method. Eg.: evas */
+       int         canvas_required; /* Whether the canvas usage is required for this input method */
+     };
+
+   EAPI int                           ecore_imf_init(void);
+   EAPI int                           ecore_imf_shutdown(void);
+
+   EAPI void                          ecore_imf_module_register(const Ecore_IMF_Context_Info *info, Ecore_IMF_Context *(*imf_module_create)(void), Ecore_IMF_Context *(*imf_module_exit)(void));
+
+   EAPI Eina_List                    *ecore_imf_context_available_ids_get(void);
+   EAPI Eina_List                    *ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type);
+   EAPI const char                   *ecore_imf_context_default_id_get(void);
+   EAPI const char                   *ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type);
+   EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_by_id_get(const char *id);
+
+   EAPI Ecore_IMF_Context            *ecore_imf_context_add(const char *id);
+   EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_get(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_del(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window);
+   EAPI void                          ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas);
+   EAPI void                          ecore_imf_context_show(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_hide(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
+   EAPI void                          ecore_imf_context_focus_in(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_focus_out(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_reset(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos);
+   EAPI void                          ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit);
+   EAPI void                          ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data);
+   EAPI void                          ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
+   EAPI Ecore_IMF_Input_Mode          ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx);
+   EAPI int                           ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
+
+   /* plugin specific functions */
+   EAPI Ecore_IMF_Context            *ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc);
+   EAPI void                          ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data);
+   EAPI void                         *ecore_imf_context_data_get(Ecore_IMF_Context *ctx);
+   EAPI int                           ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
+   EAPI void                          ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx);
+   EAPI void                          ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str);
+   EAPI void                          ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars);
+
+   /* The following entry points must be exported by each input method module
+    */
+
+   /*
+    * int                imf_module_init   (const Ecore_IMF_Context_Info **info);
+    * void               imf_module_exit   (void);
+    * Ecore_IMF_Context *imf_module_create (void);
+    */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_imf/Makefile.am b/src/lib/ecore_imf/Makefile.am
new file mode 100644 (file)
index 0000000..385ae8c
--- /dev/null
@@ -0,0 +1,30 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_IMF
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@EFL_ECORE_IMF_BUILD@ \
+@EVIL_CFLAGS@ \
+@EINA_CFLAGS@
+
+AM_CFLAGS = @WIN32_CFLAGS@
+
+lib_LTLIBRARIES = libecore_imf.la
+include_HEADERS = \
+Ecore_IMF.h
+
+libecore_imf_la_SOURCES = \
+ecore_imf.c \
+ecore_imf_context.c \
+ecore_imf_module.c
+
+libecore_imf_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EINA_LIBS@ \
+@EVIL_LIBS@
+
+libecore_imf_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_imf_release_info@
+endif
+
+EXTRA_DIST = ecore_imf_private.h
diff --git a/src/lib/ecore_imf/ecore_imf.c b/src/lib/ecore_imf/ecore_imf.c
new file mode 100644 (file)
index 0000000..e3b2915
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#include <ecore_private.h>
+
+#include "Ecore_IMF.h"
+#include "ecore_imf_private.h"
+
+EAPI int ECORE_IMF_EVENT_PREEDIT_START = 0;
+EAPI int ECORE_IMF_EVENT_PREEDIT_END = 0;
+EAPI int ECORE_IMF_EVENT_PREEDIT_CHANGED = 0;
+EAPI int ECORE_IMF_EVENT_COMMIT = 0;
+EAPI int ECORE_IMF_EVENT_DELETE_SURROUNDING = 0;
+
+int _ecore_imf_log_dom = -1;
+static int _ecore_imf_init_count = 0;
+
+/**
+ * @defgroup Ecore_IMF_Lib_Group Ecore Input Method Library Functions
+ *
+ * Utility functions that set up and shut down the Ecore Input Method
+ * library.
+ */
+
+/**
+ * Initialises the Ecore_IMF library.
+ * @return  Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_IMF_Lib_Group
+ */
+EAPI int
+ecore_imf_init(void)
+{
+   if (++_ecore_imf_init_count != 1)
+     return _ecore_imf_init_count;
+
+   if (!ecore_init())
+     return --_ecore_imf_init_count;
+   _ecore_imf_log_dom = eina_log_domain_register("EcoreIMF", ECORE_IMF_DEFAULT_LOG_COLOR);
+   if(_ecore_imf_log_dom < 0) 
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the Ecore IMF module.");
+       ecore_shutdown();
+       return --_ecore_imf_init_count;
+     }
+   ecore_imf_module_init();
+
+   ECORE_IMF_EVENT_PREEDIT_START = ecore_event_type_new();
+   ECORE_IMF_EVENT_PREEDIT_END = ecore_event_type_new();
+   ECORE_IMF_EVENT_PREEDIT_CHANGED = ecore_event_type_new();
+   ECORE_IMF_EVENT_COMMIT = ecore_event_type_new();
+   ECORE_IMF_EVENT_DELETE_SURROUNDING = ecore_event_type_new();
+
+   return _ecore_imf_init_count;
+}
+
+/**
+ * Shuts down the Ecore_IMF library.
+ * @return  Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_IMF_Lib_Group
+ */
+EAPI int
+ecore_imf_shutdown(void)
+{
+   if (--_ecore_imf_init_count != 0)
+     return _ecore_imf_init_count;
+
+   ecore_shutdown();
+   ecore_imf_module_shutdown();
+   eina_log_domain_unregister(_ecore_imf_log_dom);
+   _ecore_imf_log_dom = -1;
+   return _ecore_imf_init_count;
+}
diff --git a/src/lib/ecore_imf/ecore_imf_context.c b/src/lib/ecore_imf/ecore_imf_context.c
new file mode 100644 (file)
index 0000000..1214be0
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+
+#include <Ecore.h>
+#include <ecore_private.h>
+
+#include "Ecore_IMF.h"
+#include "ecore_imf_private.h"
+
+/**
+ * @defgroup Ecore_IMF_Context_Group Ecore Input Method Context Functions
+ *
+ * Functions that operate on Ecore Input Method Context objects.
+ */
+
+/**
+ * Get the list of the available Input Method Context ids.
+ *
+ * Note that the caller is responsible for freeing the Eina_List
+ * when finished with it. There is no need to finish the list strings.
+ *
+ * @return Return an EIna_List of strings;
+ *         on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI Eina_List *
+ecore_imf_context_available_ids_get(void)
+{
+   return ecore_imf_module_context_ids_get();
+}
+
+EAPI Eina_List *
+ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type)
+{
+   return ecore_imf_module_context_ids_by_canvas_type_get(canvas_type);
+}
+
+/*
+ * Match @locale against @against.
+ *
+ * 'en_US' against 'en_US'       => 4
+ * 'en_US' against 'en'          => 3
+ * 'en', 'en_UK' against 'en_US' => 2
+ *  all locales, against '*'     => 1
+ */
+static int
+_ecore_imf_context_match_locale(const char *locale, const char *against, int against_len)
+{
+  if (strcmp(against, "*") == 0)
+    return 1;
+
+  if (strcasecmp(locale, against) == 0)
+    return 4;
+
+  if (strncasecmp(locale, against, 2) == 0)
+    return (against_len == 2) ? 3 : 2;
+
+  return 0;
+}
+
+/**
+ * Get the id of the default Input Method Context.
+ * The id may to used to create a new instance of an Input Method
+ * Context object.
+ *
+ * @return Return a string containing the id of the default Input
+ *         Method Context; on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI const char *
+ecore_imf_context_default_id_get(void)
+{
+   return ecore_imf_context_default_id_by_canvas_type_get(NULL);
+}
+
+EAPI const char *
+ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type)
+{
+   const char *id;
+   Eina_List *modules;
+   Ecore_IMF_Module *module;
+   char *locale;
+   char *tmp;
+   int best_goodness = 0;
+
+   id = getenv("ECORE_IMF_MODULE");
+   if (id)
+     {
+       if (strcmp(id, "none") == 0) return NULL;
+       if (ecore_imf_module_get(id)) return id;
+     }
+
+   modules = ecore_imf_module_available_get();
+   if (!modules) return NULL;
+
+   locale = setlocale(LC_CTYPE, NULL);
+   if (!locale) return NULL;
+
+   locale = strdup(locale);
+
+   tmp = strchr(locale, '.');
+   if (tmp) *tmp = '\0';
+   tmp = strchr(locale, '@');
+   if (tmp) *tmp = '\0';
+
+   id = NULL;
+
+   EINA_LIST_FREE(modules, module)
+     {
+       if (canvas_type &&
+           strcmp(module->info->canvas_type, canvas_type) == 0)
+         continue;
+
+       const char *p = module->info->default_locales;
+       while (p)
+         {
+            const char *q = strchr(p, ':');
+            int goodness = _ecore_imf_context_match_locale(locale, p, q ? (size_t)(q - p) : strlen (p));
+
+             if (goodness > best_goodness)
+               {
+                  id = module->info->id;
+                  best_goodness = goodness;
+               }
+
+             p = q ? q + 1 : NULL;
+         }
+     }
+
+   free(locale);
+   return id;
+}
+
+/**
+ * Retrieve the info for the Input Method Context with @p id.
+ *
+ * @param id The Input Method Context id to query for.
+ * @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id;
+ *         on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI const Ecore_IMF_Context_Info *
+ecore_imf_context_info_by_id_get(const char *id)
+{
+   Ecore_IMF_Module *module;
+
+   if (!id) return NULL;
+   module = ecore_imf_module_get(id);
+   if (!module) return NULL;
+   return module->info;
+}
+
+/**
+ * Create a new Input Method Context defined by the given id.
+ *
+ * @param id The Input Method Context id.
+ * @return A newly allocated Input Method Context;
+ *         on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI Ecore_IMF_Context *
+ecore_imf_context_add(const char *id)
+{
+   Ecore_IMF_Context *ctx;
+
+   if (!id) return NULL;
+   ctx = ecore_imf_module_context_create(id);
+   if (!ctx || !ctx->klass) return NULL;
+   if (ctx->klass->add) ctx->klass->add(ctx);
+   /* default use_preedit is 1, so let's make sure it's
+    * set on the immodule */
+   ecore_imf_context_use_preedit_set(ctx, 1);
+   /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
+    * set on the immodule */
+   ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
+   return ctx;
+}
+
+/**
+ * Retrieve the info for the given Input Method Context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @return Return a #Ecore_IMF_Context_Info for the given Input Method Context;
+ *         on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI const Ecore_IMF_Context_Info *
+ecore_imf_context_info_get(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_info_get");
+       return NULL;
+     }
+   return ctx->module->info;
+}
+
+/**
+ * Delete the given Input Method Context and free its memory.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_del(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_del");
+       return;
+     }
+   if (ctx->klass->del) ctx->klass->del(ctx);
+   ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
+   free(ctx);
+}
+
+/**
+ * Set the client window for the Input Method Context; this is the
+ * Ecore_X_Window when using X11, Ecore_Win32_Window when using Win32, etc.
+ * This window is used in order to correctly position status windows, and may
+ * also be used for purposes internal to the Input Method Context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param window The client window. This may be NULL to indicate
+ *               that the previous client window no longer exists.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_client_window_set");
+       return;
+     }
+   if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
+}
+
+/**
+ * Set the client canvas for the Input Method Context; this is the
+ * canvas in which the input appears.
+ * The canvas type can be determined by using the context canvas type.
+ * Actually only canvas with type "evas" (Evas *) is supported.
+ * This canvas may be used in order to correctly position status windows, and may
+ * also be used for purposes internal to the Input Method Context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param canas The client canvas. This may be NULL to indicate
+ *              that the previous client canvas no longer exists.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_client_window_set");
+       return;
+     }
+   if (ctx->klass->client_canvas_set) ctx->klass->client_canvas_set(ctx, canvas);
+}
+
+/**
+ * Ask the Input Method Context to show itself.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_show(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_show");
+       return;
+     }
+   if (ctx->klass->show) ctx->klass->show(ctx);
+}
+
+/**
+ * Ask the Input Method Context to hide itself.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_hide(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_hide");
+       return;
+     }
+   if (ctx->klass->hide) ctx->klass->hide(ctx);
+}
+
+/*
+ * Retrieve the current preedit string and cursor position
+ * for the Input Method Context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param str Location to store the retrieved string. The
+ *            string retrieved must be freed with free().
+ * @param cursor_pos Location to store position of cursor (in characters)
+ *                   within the preedit string.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_preedit_string_get");
+       return;
+     }
+   if (ctx->klass->preedit_string_get)
+     ctx->klass->preedit_string_get(ctx, str, cursor_pos);
+   else
+     {
+       if (str) *str = strdup("");
+       if (cursor_pos) *cursor_pos = 0;
+     }
+}
+
+/**
+ * Notify the Input Method Context that the widget to which its
+ * correspond has gained focus.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_focus_in");
+       return;
+     }
+   if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
+}
+
+/**
+ * Notify the Input Method Context that the widget to which its
+ * correspond has lost focus.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_focus_out");
+       return;
+     }
+   if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
+}
+
+/**
+ * Notify the Input Method Context that a change such as a
+ * change in cursor position has been made. This will typically
+ * cause the Input Method Context to clear the preedit state.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_reset(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_reset");
+       return;
+     }
+   if (ctx->klass->reset) ctx->klass->reset(ctx);
+}
+
+/**
+ * Notify the Input Method Context that a change in the cursor
+ * position has been made.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param cursor_pos New cursor position in characters.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_cursor_position_set");
+       return;
+     }
+   if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
+}
+
+/**
+ * Set whether the IM context should use the preedit string
+ * to display feedback. If @use_preedit is 0 (default
+ * is 1), then the IM context may use some other method to display
+ * feedback, such as displaying it in a child of the root window.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param use_preedit Whether the IM context should use the preedit string.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_use_preedit_set");
+       return;
+     }
+   if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
+}
+
+/**
+ * Set the callback to be used on get_surrounding request.
+ *
+ * This callback will be called when the Input Method Context
+ * module requests the surrounding context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param func The callback to be called.
+ * @param data The data pointer to be passed to @p func
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_retrieve_surrounding_callback_set");
+       return;
+     }
+
+   ctx->retrieve_surrounding_func = func;
+   ctx->retrieve_surrounding_data = (void *) data;
+}
+
+/**
+ * Set the input mode used by the Ecore Input Context.
+ *
+ * The input mode can be one of the input modes defined in
+ * #Ecore_IMF_Input_Mode. The default input mode is
+ * ECORE_IMF_INPUT_MODE_FULL.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param input_mode The input mode to be used by @p ctx.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI void
+ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_input_mode_set");
+       return;
+     }
+   if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
+   ctx->input_mode = input_mode;
+}
+
+/**
+ * Get the input mode being used by the Ecore Input Context.
+ *
+ * See @ref ecore_imf_context_input_mode_set for more details.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @return The input mode being used by @p ctx.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI Ecore_IMF_Input_Mode
+ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_input_mode_set");
+       return 0;
+     }
+   return ctx->input_mode;
+}
+
+/**
+ * Allow an Ecore Input Context to internally handle an event.
+ * If this function returns 1, then no further processing
+ * should be done for this event.
+ *
+ * Input methods must be able to accept all types of events (simply
+ * returning 0 if the event was not handled), but there is no
+ * obligation of any events to be submitted to this function.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param type The type of event defined by #Ecore_IMF_Event_Type.
+ * @param event The event itself.
+ * @return 1 if the event was handled; otherwise 0.
+ * @ingroup Ecore_IMF_Context_Group
+ */
+EAPI int
+ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_filter_event");
+       return 0;
+     }
+   if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event);
+   return 0;
+}
+
+/**
+ * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
+ *
+ * Functions that should be used by Ecore Input Method Context modules.
+ */
+
+/**
+ * Creates a new Input Method Context with klass specified by @p ctxc.
+ *
+ * This method should be used by modules implementing the Input
+ * Method Context interface.
+ *
+ * @param ctxc An #Ecore_IMF_Context_Class.
+ * @return A new #Ecore_IMF_Context; on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI Ecore_IMF_Context *
+ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
+{
+   Ecore_IMF_Context *ctx;
+
+   if (!ctxc) return NULL;
+   ctx = malloc(sizeof(Ecore_IMF_Context));
+   if (!ctx) return NULL;
+   ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
+   ctx->klass = ctxc;
+   ctx->data = NULL;
+   ctx->retrieve_surrounding_func = NULL;
+   ctx->retrieve_surrounding_data = NULL;
+   return ctx;
+}
+
+/**
+ * Set the Input Method Context specific data.
+ *
+ * Note that this method should be used by modules to set
+ * the Input Method Context specific data and it's not meant to
+ * be used by applications to store application specific data.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param data The Input Method Context specific data.
+ * @return A new #Ecore_IMF_Context; on failure it returns NULL.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_data_set");
+       return;
+     }
+   ctx->data = data;
+}
+
+/**
+ * Get the Input Method Context specific data.
+ *
+ * See @ref ecore_imf_context_data_set for more details.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @return The Input Method Context specific data.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
+{
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_data_get");
+       return NULL;
+     }
+   return ctx->data;
+}
+
+/**
+ * Retrieve context around insertion point.
+ *
+ * This function is implemented by calling the
+ * Ecore_IMF_Context::retrieve_surrounding_func (
+ * set using #ecore_imf_context_retrieve_surrounding_callback_set).
+ *
+ * There is no obligation for a widget to respond to the
+ * ::retrieve_surrounding_func, so input methods must be prepared
+ * to function without context.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param text Location to store a UTF-8 encoded string of text
+ *             holding context around the insertion point.
+ *             If the function returns 1, then you must free
+ *             the result stored in this location with free().
+ * @param cursor_pos Location to store the position in characters of
+ *                   the insertion cursor within @text.
+ * @return 1 if surrounding text was provided; otherwise 0.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI int
+ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
+{
+   int result = 0;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_surrounding_get");
+       return 0;
+     }
+
+   if (ctx->retrieve_surrounding_func)
+     {
+       result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
+       if (!result)
+         {
+            if (text) *text = NULL;
+            if (cursor_pos) *cursor_pos = 0;
+         }
+     }
+   return result;
+}
+
+static void
+_ecore_imf_event_free_preedit(void *data __UNUSED__, void *event)
+{
+   free(event);
+}
+
+/**
+ * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
+{
+   Ecore_IMF_Event_Commit *ev;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_preedit_start_event_add");
+       return;
+     }
+
+   ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
+   ev->ctx = ctx;
+   ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
+                  ev, _ecore_imf_event_free_preedit, NULL);
+}
+
+/**
+ * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
+{
+   Ecore_IMF_Event_Commit *ev;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_preedit_end_event_add");
+       return;
+     }
+
+   ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
+   ev->ctx = ctx;
+   ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
+                  ev, _ecore_imf_event_free_preedit, NULL);
+}
+
+/**
+ * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
+{
+   Ecore_IMF_Event_Commit *ev;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_preedit_changed_event_add");
+       return;
+     }
+
+   ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));
+   ev->ctx = ctx;
+   ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED,
+                  ev, _ecore_imf_event_free_preedit, NULL);
+}
+
+static void
+_ecore_imf_event_free_commit(void *data __UNUSED__, void *event)
+{
+   Ecore_IMF_Event_Commit *ev;
+
+   ev = event;
+   if (ev->str) free(ev->str);
+   free(ev);
+}
+
+/**
+ * Adds ECORE_IMF_EVENT_COMMIT to the event queue.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param str The committed string.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str)
+{
+   Ecore_IMF_Event_Commit *ev;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_commit_event_add");
+       return;
+     }
+
+   ev = malloc(sizeof(Ecore_IMF_Event_Commit));
+   ev->ctx = ctx;
+   ev->str = str ? strdup(str) : NULL;
+   ecore_event_add(ECORE_IMF_EVENT_COMMIT,
+                  ev, _ecore_imf_event_free_commit, NULL);
+
+}
+
+static void
+_ecore_imf_event_free_delete_surrounding(void *data __UNUSED__, void *event)
+{
+   free(event);
+}
+
+/**
+ * Adds ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
+ *
+ * @param ctx An #Ecore_IMF_Context.
+ * @param offset The start offset of surrounding to be deleted.
+ * @param n_chars The number of characters to be deleted.
+ * @ingroup Ecore_IMF_Context_Module_Group
+ */
+EAPI void
+ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars)
+{
+   Ecore_IMF_Event_Delete_Surrounding *ev;
+
+   if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+     {
+       ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                        "ecore_imf_context_delete_surrounding_event_add");
+       return;
+     }
+
+   ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding));
+   ev->ctx = ctx;
+   ev->offset = offset;
+   ev->n_chars = n_chars;
+   ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDING,
+                  ev, _ecore_imf_event_free_delete_surrounding, NULL);
+}
diff --git a/src/lib/ecore_imf/ecore_imf_module.c b/src/lib/ecore_imf/ecore_imf_module.c
new file mode 100644 (file)
index 0000000..0bf24f8
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <Ecore.h>
+#include <ecore_private.h>
+
+#include "Ecore_IMF.h"
+#include "ecore_imf_private.h"
+
+static void _ecore_imf_module_free(Ecore_IMF_Module *module);
+static int _ecore_imf_modules_exists(const char *ctx_id);
+
+typedef struct _Ecore_IMF_Selector
+{
+  const char   *toselect;
+  void         *selected;
+} Ecore_IMF_Selector;
+
+static Eina_Hash *modules = NULL;
+static Eina_Array *module_list = NULL;
+
+void
+ecore_imf_module_init(void)
+{
+   char *homedir;
+
+   module_list = eina_module_list_get(NULL, PACKAGE_LIB_DIR "/ecore/immodules", 0, NULL, NULL);
+   homedir = eina_module_environment_path_get("HOME", "/.ecore/immodules");
+   if (homedir)
+     {
+       module_list = eina_module_list_get(module_list, homedir, 0, NULL, NULL);
+       free(homedir);
+     }
+   eina_module_list_load(module_list);
+}
+
+void
+ecore_imf_module_shutdown(void)
+{
+   if (modules)
+     {
+       eina_hash_free(modules);
+       modules = NULL;
+     }
+   if (module_list)
+     {
+       eina_module_list_free(module_list);
+       modules = NULL;
+     }
+}
+
+static Eina_Bool
+_hash_module_available_get(const Eina_Hash *hash __UNUSED__, int *data, void *list)
+{
+  *(Eina_List**)list = eina_list_append(*(Eina_List**)list, data);
+  return EINA_TRUE;
+}
+
+Eina_List *
+ecore_imf_module_available_get(void)
+{
+   Eina_List *values = NULL;
+   Eina_Iterator *it = NULL;
+
+   if (!modules) return NULL;
+
+   it = eina_hash_iterator_data_new(modules);
+   if (!it)
+       return NULL;
+
+   eina_iterator_foreach(it, EINA_EACH(_hash_module_available_get), &values);
+   eina_iterator_free(it);
+
+   return values;
+}
+
+Ecore_IMF_Module *
+ecore_imf_module_get(const char *ctx_id)
+{
+   if (!modules) return NULL;
+   return eina_hash_find(modules, ctx_id);
+}
+
+Ecore_IMF_Context *
+ecore_imf_module_context_create(const char *ctx_id)
+{
+   Ecore_IMF_Module *module;
+   Ecore_IMF_Context *ctx = NULL;
+
+   if (!modules) return NULL;
+   module = eina_hash_find(modules, ctx_id);
+   if (module)
+     {
+       ctx = module->create();
+       if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
+         {
+            ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
+                             "ecore_imf_module_context_create");
+            return NULL;
+         }
+       ctx->module = module;
+     }
+   return ctx;
+}
+
+static Eina_Bool
+_hash_ids_get(const Eina_Hash *hash __UNUSED__, const char *key, void *list)
+{
+  *(Eina_List**)list = eina_list_append(*(Eina_List**)list, key);
+  return EINA_TRUE;
+}
+
+Eina_List *
+ecore_imf_module_context_ids_get(void)
+{
+   Eina_List *l = NULL;
+   Eina_Iterator *it = NULL;
+
+   if (!modules) return NULL;
+
+   it = eina_hash_iterator_key_new(modules);
+   if (!it)
+       return NULL;
+
+   eina_iterator_foreach(it, EINA_EACH(_hash_ids_get), &l);
+   eina_iterator_free(it);
+
+   return l;
+}
+
+static Eina_Bool
+_hash_ids_by_canvas_type_get(const Eina_Hash *hash __UNUSED__, void *data, void *fdata)
+{
+   Ecore_IMF_Module *module = data;
+   Ecore_IMF_Selector *selector = fdata;
+
+   if (!strcmp(module->info->canvas_type, selector->toselect))
+     selector->selected = eina_list_append(selector->selected, (void *)module->info->id);
+
+   return EINA_TRUE;
+}
+
+Eina_List *
+ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type)
+{
+   Ecore_IMF_Selector selector;
+   Eina_List *values = NULL;
+   Eina_Iterator *it = NULL;
+
+   if (!modules) return NULL;
+
+   if (!canvas_type)
+     return ecore_imf_module_context_ids_get();
+
+   it = eina_hash_iterator_data_new(modules);
+   if (!it)
+       return NULL;
+
+   selector.toselect = canvas_type;
+   selector.selected = values;
+   eina_iterator_foreach(it, EINA_EACH(_hash_ids_by_canvas_type_get), &selector);
+   eina_iterator_free(it);
+
+   return values;
+}
+
+EAPI void
+ecore_imf_module_register(const Ecore_IMF_Context_Info *info,
+                         Ecore_IMF_Context *(*imf_module_create)(void),
+                         Ecore_IMF_Context *(*imf_module_exit)(void))
+{
+   Ecore_IMF_Module *module;
+
+   if (_ecore_imf_modules_exists(info->id)) return;
+
+   if (!modules)
+     modules = eina_hash_string_superfast_new(EINA_FREE_CB(_ecore_imf_module_free));
+
+   module = malloc(sizeof(Ecore_IMF_Module));
+   module->info = info;
+   /* cache imf_module_create as it may be used several times */
+   module->create = imf_module_create;
+   module->exit = imf_module_exit;
+
+   eina_hash_add(modules, info->id, module);
+}
+
+static void
+_ecore_imf_module_free(Ecore_IMF_Module *module)
+{
+   if (module->exit) module->exit();
+   free(module);
+}
+
+static int
+_ecore_imf_modules_exists(const char *ctx_id)
+{
+   if (!modules) return 0;
+   if (!ctx_id) return 0;
+
+   if (eina_hash_find(modules, ctx_id))
+     return 1;
+
+   return 0;
+}
diff --git a/src/lib/ecore_imf/ecore_imf_private.h b/src/lib/ecore_imf/ecore_imf_private.h
new file mode 100644 (file)
index 0000000..23b8301
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef _ECORE_IMF_PRIVATE_H
+#define _ECORE_IMF_PRIVATE_H
+
+#define ECORE_MAGIC_CONTEXT 0x56c1b39a
+
+#ifdef ECORE_IMF_DEFAULT_LOG_COLOR
+#undef ECORE_IMF_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_IMF_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+extern int _ecore_imf_log_dom;
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_imf_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_imf_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_imf_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_imf_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_imf_log_dom, __VA_ARGS__)
+
+typedef struct _Ecore_IMF_Module Ecore_IMF_Module;
+
+struct _Ecore_IMF_Context
+{
+   ECORE_MAGIC;
+   const Ecore_IMF_Module        *module;
+   const Ecore_IMF_Context_Class *klass;
+   void                          *data;
+   int                            input_mode;
+   int                          (*retrieve_surrounding_func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
+   void                          *retrieve_surrounding_data;
+};
+
+struct _Ecore_IMF_Module
+{
+   const Ecore_IMF_Context_Info *info;
+   Ecore_IMF_Context            *(*create)(void);
+   Ecore_IMF_Context            *(*exit)(void);
+};
+
+void               ecore_imf_module_init(void);
+void               ecore_imf_module_shutdown(void);
+Eina_List         *ecore_imf_module_available_get(void);
+Ecore_IMF_Module  *ecore_imf_module_get(const char *ctx_id);
+Ecore_IMF_Context *ecore_imf_module_context_create(const char *ctx_id);
+Eina_List         *ecore_imf_module_context_ids_get(void);
+Eina_List         *ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type);
+
+#endif
diff --git a/src/lib/ecore_imf_evas/.cvsignore b/src/lib/ecore_imf_evas/.cvsignore
new file mode 100644 (file)
index 0000000..09980ae
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/ecore_imf_evas/Ecore_IMF_Evas.h b/src/lib/ecore_imf_evas/Ecore_IMF_Evas.h
new file mode 100644 (file)
index 0000000..ea99324
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#ifndef _ECORE_IMF_EVAS_H
+#define _ECORE_IMF_EVAS_H
+
+#include <Ecore_IMF.h>
+#include <Evas.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_IMF_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_EVAS_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   EAPI void ecore_imf_evas_event_mouse_in_wrap(Evas_Event_Mouse_In *evas_event, Ecore_IMF_Event_Mouse_In *imf_event);
+   EAPI void ecore_imf_evas_event_mouse_out_wrap(Evas_Event_Mouse_Out *evas_event, Ecore_IMF_Event_Mouse_Out *imf_event);
+   EAPI void ecore_imf_evas_event_mouse_move_wrap(Evas_Event_Mouse_Move *evas_event, Ecore_IMF_Event_Mouse_Move *imf_event);
+   EAPI void ecore_imf_evas_event_mouse_down_wrap(Evas_Event_Mouse_Down *evas_event, Ecore_IMF_Event_Mouse_Down *imf_event);
+   EAPI void ecore_imf_evas_event_mouse_up_wrap(Evas_Event_Mouse_Up *evas_event, Ecore_IMF_Event_Mouse_Up *imf_event);
+   EAPI void ecore_imf_evas_event_mouse_wheel_wrap(Evas_Event_Mouse_Wheel *evas_event, Ecore_IMF_Event_Mouse_Wheel *imf_event);
+   EAPI void ecore_imf_evas_event_key_down_wrap(Evas_Event_Key_Down *evas_event, Ecore_IMF_Event_Key_Down *imf_event);
+   EAPI void ecore_imf_evas_event_key_up_wrap(Evas_Event_Key_Up *evas_event, Ecore_IMF_Event_Key_Up *imf_event);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_imf_evas/Makefile.am b/src/lib/ecore_imf_evas/Makefile.am
new file mode 100644 (file)
index 0000000..2455944
--- /dev/null
@@ -0,0 +1,24 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_IMF_EVAS
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_imf \
+@EFL_ECORE_IMF_BUILD@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+lib_LTLIBRARIES = libecore_imf_evas.la
+include_HEADERS = \
+Ecore_IMF_Evas.h
+
+libecore_imf_evas_la_SOURCES = \
+ecore_imf_evas.c
+
+libecore_imf_evas_la_LIBADD = \
+$(top_builddir)/src/lib/ecore_imf/libecore_imf.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@
+
+libecore_imf_evas_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_imf_evas_release_info@
+endif
diff --git a/src/lib/ecore_imf_evas/ecore_imf_evas.c b/src/lib/ecore_imf_evas/ecore_imf_evas.c
new file mode 100644 (file)
index 0000000..b14f5dd
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore_IMF_Evas.h"
+
+/**
+ * @defgroup Ecore_IMF_Evas_Group Ecore Input Method Context Evas Helper Functions
+ *
+ * Helper functions to make it easy to use Evas with Ecore_IMF.
+ */
+
+static const char *_ecore_imf_evas_event_empty = "";
+
+/* Converts the Evas modifiers to Ecore_IMF keyboard modifiers */
+static void
+_ecore_imf_evas_event_modifiers_wrap(Evas_Modifier *evas_modifiers,
+                                    Ecore_IMF_Keyboard_Modifiers *imf_keyboard_modifiers)
+{
+   if (!evas_modifiers || !imf_keyboard_modifiers)
+     return;
+
+   *imf_keyboard_modifiers = ECORE_IMF_KEYBOARD_MODIFIER_NONE;
+   if (evas_key_modifier_is_set(evas_modifiers, "Control"))
+     *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
+   if (evas_key_modifier_is_set(evas_modifiers, "Alt"))
+     *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
+   if (evas_key_modifier_is_set(evas_modifiers, "Shift"))
+     *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
+   if (evas_key_modifier_is_set(evas_modifiers, "Super") || evas_key_modifier_is_set(evas_modifiers, "Hyper"))
+     *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
+}
+
+/* Converts the Evas locks to Ecore_IMF keyboard locks */
+static void
+_ecore_imf_evas_event_locks_wrap(Evas_Lock *evas_locks,
+                                Ecore_IMF_Keyboard_Locks *imf_keyboard_locks)
+{
+   if (!evas_locks || !imf_keyboard_locks)
+     return;
+
+   *imf_keyboard_locks = ECORE_IMF_KEYBOARD_LOCK_NONE;
+   if (evas_key_lock_is_set(evas_locks, "Num_Lock"))
+     *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
+   if (evas_key_lock_is_set(evas_locks, "Caps_Lock"))
+     *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
+   if (evas_key_lock_is_set(evas_locks, "Scroll_Lock"))
+     *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
+}
+
+/* Converts the Evas mouse flags to Ecore_IMF mouse flags */
+static void
+_ecore_imf_evas_event_mouse_flags_wrap(Evas_Button_Flags evas_flags,
+                                      Ecore_IMF_Mouse_Flags *imf_flags)
+{
+   if (!imf_flags)
+     return;
+
+   *imf_flags = ECORE_IMF_MOUSE_NONE;
+   if (evas_flags & EVAS_BUTTON_DOUBLE_CLICK)
+     *imf_flags |= ECORE_IMF_MOUSE_DOUBLE_CLICK;
+   if (evas_flags & EVAS_BUTTON_TRIPLE_CLICK)
+     *imf_flags |= ECORE_IMF_MOUSE_TRIPLE_CLICK;
+}
+
+/**
+ * Converts a "mouse_in" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_in_wrap(Evas_Event_Mouse_In *evas_event,
+                                  Ecore_IMF_Event_Mouse_In *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->buttons = evas_event->buttons;
+   imf_event->output.x = evas_event->output.x;
+   imf_event->output.y = evas_event->output.y;
+   imf_event->canvas.x = evas_event->canvas.x;
+   imf_event->canvas.y = evas_event->canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+}
+
+/**
+ * Converts a "mouse_out" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_out_wrap(Evas_Event_Mouse_Out *evas_event,
+                                   Ecore_IMF_Event_Mouse_Out *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->buttons = evas_event->buttons;
+   imf_event->output.x = evas_event->output.x;
+   imf_event->output.y = evas_event->output.y;
+   imf_event->canvas.x = evas_event->canvas.x;
+   imf_event->canvas.y = evas_event->canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+}
+
+/**
+ * Converts a "mouse_move" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_move_wrap(Evas_Event_Mouse_Move *evas_event,
+                                    Ecore_IMF_Event_Mouse_Move *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->buttons = evas_event->buttons;
+   imf_event->cur.output.x = evas_event->cur.output.x;
+   imf_event->cur.output.y = evas_event->cur.output.y;
+   imf_event->prev.output.x = evas_event->prev.output.x;
+   imf_event->prev.output.y = evas_event->prev.output.y;
+   imf_event->cur.canvas.x = evas_event->cur.canvas.x;
+   imf_event->cur.canvas.y = evas_event->cur.canvas.y;
+   imf_event->prev.canvas.x = evas_event->prev.canvas.x;
+   imf_event->prev.canvas.y = evas_event->prev.canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+}
+
+/**
+ * Converts a "mouse_down" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_down_wrap(Evas_Event_Mouse_Down *evas_event,
+                                    Ecore_IMF_Event_Mouse_Down *imf_event)
+{
+   if (!evas_event || !imf_event)
+      return;
+
+   imf_event->button = evas_event->button;
+   imf_event->output.x = evas_event->output.x;
+   imf_event->output.y = evas_event->output.y;
+   imf_event->canvas.x = evas_event->canvas.x;
+   imf_event->canvas.y = evas_event->canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+   _ecore_imf_evas_event_mouse_flags_wrap(evas_event->flags, &imf_event->flags);
+}
+
+/**
+ * Converts a "mouse_up" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_up_wrap(Evas_Event_Mouse_Up *evas_event,
+                                  Ecore_IMF_Event_Mouse_Up *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->button = evas_event->button;
+   imf_event->output.x = evas_event->output.x;
+   imf_event->output.y = evas_event->output.y;
+   imf_event->canvas.x = evas_event->canvas.x;
+   imf_event->canvas.y = evas_event->canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+   _ecore_imf_evas_event_mouse_flags_wrap(evas_event->flags, &imf_event->flags);
+}
+
+/**
+ * Converts a "mouse_wheel" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_mouse_wheel_wrap(Evas_Event_Mouse_Wheel *evas_event,
+                                     Ecore_IMF_Event_Mouse_Wheel *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->direction = evas_event->direction;
+   imf_event->z = evas_event->z;
+   imf_event->output.x = evas_event->output.x;
+   imf_event->output.y = evas_event->output.y;
+   imf_event->canvas.x = evas_event->canvas.x;
+   imf_event->canvas.y = evas_event->canvas.y;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+   imf_event->timestamp = evas_event->timestamp;
+}
+
+/**
+ * Converts a "key_down" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_key_down_wrap(Evas_Event_Key_Down *evas_event,
+                                  Ecore_IMF_Event_Key_Down *imf_event)
+{
+   if (!evas_event || !imf_event)
+     return;
+
+   imf_event->keyname = evas_event->keyname ? evas_event->keyname : _ecore_imf_evas_event_empty;
+   imf_event->key = evas_event->key ? evas_event->key : _ecore_imf_evas_event_empty;
+   imf_event->string = evas_event->string ? evas_event->string : _ecore_imf_evas_event_empty;
+   imf_event->compose = evas_event->compose ? evas_event->compose : _ecore_imf_evas_event_empty;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+}
+
+/**
+ * Converts a "key_up" event from Evas to the corresponding event of Ecore_IMF.
+ *
+ * @param evas_event The received Evas event.
+ * @param imf_event The location to store the converted Ecore_IMF event.
+ * @ingroup Ecore_IMF_Evas_Group
+ */
+EAPI void
+ecore_imf_evas_event_key_up_wrap(Evas_Event_Key_Up *evas_event,
+                                Ecore_IMF_Event_Key_Up *imf_event)
+{
+   imf_event->keyname = evas_event->keyname ? evas_event->keyname : _ecore_imf_evas_event_empty;
+   imf_event->key = evas_event->key ? evas_event->key : _ecore_imf_evas_event_empty;
+   imf_event->string = evas_event->string ? evas_event->string : _ecore_imf_evas_event_empty;
+   imf_event->compose = evas_event->compose ? evas_event->compose : _ecore_imf_evas_event_empty;
+   imf_event->timestamp = evas_event->timestamp;
+   _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
+   _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
+}
diff --git a/src/lib/ecore_input/Ecore_Input.h b/src/lib/ecore_input/Ecore_Input.h
new file mode 100644 (file)
index 0000000..883e300
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_INPUT_H
+#define _ECORE_INPUT_H
+
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_INPUT_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_INPUT_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EAPI extern int ECORE_EVENT_KEY_DOWN;
+EAPI extern int ECORE_EVENT_KEY_UP;
+EAPI extern int ECORE_EVENT_MOUSE_BUTTON_DOWN;
+EAPI extern int ECORE_EVENT_MOUSE_BUTTON_UP;
+EAPI extern int ECORE_EVENT_MOUSE_MOVE;
+EAPI extern int ECORE_EVENT_MOUSE_WHEEL;
+EAPI extern int ECORE_EVENT_MOUSE_IN;
+EAPI extern int ECORE_EVENT_MOUSE_OUT;
+
+#define ECORE_EVENT_MODIFIER_SHIFT     0x0001
+#define ECORE_EVENT_MODIFIER_CTRL      0x0002
+#define ECORE_EVENT_MODIFIER_ALT       0x0004
+#define ECORE_EVENT_MODIFIER_WIN       0x0008
+#define ECORE_EVENT_MODIFIER_SCROLL    0x0010
+#define ECORE_EVENT_MODIFIER_NUM       0x0020
+#define ECORE_EVENT_MODIFIER_CAPS      0x0040
+#define ECORE_EVENT_LOCK_SCROLL                0x0080
+#define ECORE_EVENT_LOCK_NUM           0x0100
+#define ECORE_EVENT_LOCK_CAPS          0x0200
+
+typedef uintptr_t Ecore_Window;
+
+typedef struct _Ecore_Event_Key Ecore_Event_Key;
+struct _Ecore_Event_Key
+{
+   const char  *keyname;
+   const char  *key;
+   const char  *string;
+   const char  *compose;
+   Ecore_Window  window;
+   Ecore_Window  root_window;
+   Ecore_Window         event_window;
+
+   unsigned int         timestamp;
+   unsigned int  modifiers;
+
+   int           same_screen;
+};
+
+typedef struct _Ecore_Event_Mouse_Button Ecore_Event_Mouse_Button;
+struct _Ecore_Event_Mouse_Button
+{
+   Ecore_Window  window;
+   Ecore_Window  root_window;
+   Ecore_Window         event_window;
+
+   unsigned int         timestamp;
+   unsigned int         modifiers;
+   unsigned int  buttons;
+   unsigned int  double_click;
+   unsigned int  triple_click;
+   int           same_screen;
+
+   int          x;
+   int          y;
+   struct
+   {
+      int       x;
+      int       y;
+   } root;
+   
+   struct
+     {
+        int        device; /* 0 if normal mouse, 1+ for other mouse-devices (eg multi-touch - other fingers) */
+        double     radius, radius_x, radius_y; /* radius of press point - radius_x and y if its an ellipse (radius is the average of the 2) */
+        double     pressure; /* pressure - 1.0 == normal, > 1.0 == more, 0.0 == none */
+        double     angle; /* angle relative to perpendicular (0.0 == perpendicular), in degrees */
+        double     x, y; /* same as x, y root.x, root.y, but with sub-pixel precision, if available */
+        struct
+          {
+             double  x, y;
+          } root;
+     } multi;
+};
+
+typedef struct _Ecore_Event_Mouse_Wheel Ecore_Event_Mouse_Wheel;
+struct _Ecore_Event_Mouse_Wheel
+{
+   Ecore_Window         window;
+   Ecore_Window  root_window;
+   Ecore_Window         event_window;
+
+   unsigned int         timestamp;
+   unsigned int         modifiers;
+
+   int           same_screen;
+   int          direction;
+   int          z;
+
+   int          x;
+   int          y;
+   struct
+   {
+      int       x;
+      int       y;
+   } root;
+};
+
+typedef struct _Ecore_Event_Mouse_Move Ecore_Event_Mouse_Move;
+struct _Ecore_Event_Mouse_Move
+{
+   Ecore_Window         window;
+   Ecore_Window  root_window;
+   Ecore_Window         event_window;
+
+   unsigned int         timestamp;
+   unsigned int         modifiers;
+
+   int           same_screen;
+
+   int          x;
+   int          y;
+   struct
+   {
+      int       x;
+      int       y;
+   } root;
+
+   struct
+     {
+        int        device; /* 0 if normal mouse, 1+ for other mouse-devices (eg multi-touch - other fingers) */
+        double     radius, radius_x, radius_y; /* radius of press point - radius_x and y if its an ellipse (radius is the average of the 2) */
+        double     pressure; /* pressure - 1.0 == normal, > 1.0 == more, 0.0 == none */
+        double     angle; /* angle relative to perpendicular (0.0 == perpendicular), in degrees */
+        double     x, y; /* same as x, y root.x, root.y, but with sub-pixel precision, if available */
+        struct
+          {
+             double  x, y;
+          } root;
+     } multi;
+};
+
+typedef struct _Ecore_Event_Mouse_IO Ecore_Event_Mouse_IO;
+struct _Ecore_Event_Mouse_IO
+{
+   Ecore_Window         window;
+   Ecore_Window         event_window;
+
+   unsigned int         timestamp;
+   unsigned int  modifiers;
+
+   int          x;
+   int          y;
+};
+
+enum _Ecore_Event_Modifier
+{
+  ECORE_NONE,
+  ECORE_SHIFT,
+  ECORE_CTRL,
+  ECORE_ALT,
+  ECORE_WIN,
+  ECORE_SCROLL,
+  ECORE_CAPS,
+  ECORE_LAST
+};
+
+enum _Ecore_Event_Press
+{
+  ECORE_DOWN,
+  ECORE_UP
+};
+
+enum _Ecore_Event_IO
+{
+  ECORE_IN,
+  ECORE_OUT
+};
+
+typedef enum _Ecore_Event_IO Ecore_Event_IO;
+typedef enum _Ecore_Event_Press Ecore_Event_Press;
+typedef enum _Ecore_Event_Modifier Ecore_Event_Modifier;
+
+typedef struct _Ecore_Event_Modifiers Ecore_Event_Modifiers;
+struct _Ecore_Event_Modifiers
+{
+   unsigned int size;
+   unsigned int array[ECORE_LAST];
+};
+
+EAPI int        ecore_event_init(void);
+EAPI int        ecore_event_shutdown(void);
+
+EAPI unsigned int ecore_event_modifier_mask(Ecore_Event_Modifier modifier);
+EAPI Ecore_Event_Modifier ecore_event_update_modifier(const char *key, Ecore_Event_Modifiers *modifiers, int inc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_input/Makefile.am b/src/lib/ecore_input/Makefile.am
new file mode 100644 (file)
index 0000000..4a666c2
--- /dev/null
@@ -0,0 +1,27 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore \
+@EFL_ECORE_INPUT_BUILD@ \
+@EINA_CFLAGS@ \
+@EVIL_CFLAGS@
+
+if BUILD_ECORE_INPUT
+
+lib_LTLIBRARIES = libecore_input.la
+include_HEADERS = Ecore_Input.h
+
+libecore_input_la_SOURCES = \
+ecore_input.c
+
+libecore_input_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EINA_LIBS@ \
+@EVIL_LIBS@
+
+libecore_input_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_input_release_info@
+
+endif
+
+EXTRA_DIST = ecore_input_private.h
diff --git a/src/lib/ecore_input/ecore_input.c b/src/lib/ecore_input/ecore_input.c
new file mode 100644 (file)
index 0000000..448772e
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+
+#include "Ecore_Input.h"
+#include "ecore_input_private.h"
+
+
+int _ecore_input_log_dom = -1;
+
+EAPI int ECORE_EVENT_KEY_DOWN = 0;
+EAPI int ECORE_EVENT_KEY_UP = 0;
+EAPI int ECORE_EVENT_MOUSE_BUTTON_DOWN = 0;
+EAPI int ECORE_EVENT_MOUSE_BUTTON_UP = 0;
+EAPI int ECORE_EVENT_MOUSE_MOVE = 0;
+EAPI int ECORE_EVENT_MOUSE_WHEEL = 0;
+EAPI int ECORE_EVENT_MOUSE_IN = 0;
+EAPI int ECORE_EVENT_MOUSE_OUT = 0;
+
+static int _ecore_event_init_count = 0;
+
+EAPI int
+ecore_event_init(void)
+{
+   if (++_ecore_event_init_count != 1)
+     return _ecore_event_init_count;
+   
+   _ecore_input_log_dom = eina_log_domain_register("EcoreInput", ECORE_INPUT_DEFAULT_LOG_COLOR);
+   if(_ecore_input_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the ecore input module.");
+       return --_ecore_event_init_count;
+     }
+
+   ECORE_EVENT_KEY_DOWN = ecore_event_type_new();
+   ECORE_EVENT_KEY_UP = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_BUTTON_DOWN = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_BUTTON_UP = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_MOVE = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_WHEEL = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_IN = ecore_event_type_new();
+   ECORE_EVENT_MOUSE_OUT = ecore_event_type_new();
+
+   return _ecore_event_init_count;
+}
+
+EAPI int
+ecore_event_shutdown(void)
+{
+   if (--_ecore_event_init_count != 0)
+     return _ecore_event_init_count;
+
+   ECORE_EVENT_KEY_DOWN = 0;
+   ECORE_EVENT_KEY_UP = 0;
+   ECORE_EVENT_MOUSE_BUTTON_DOWN = 0;
+   ECORE_EVENT_MOUSE_BUTTON_UP = 0;
+   ECORE_EVENT_MOUSE_MOVE = 0;
+   ECORE_EVENT_MOUSE_WHEEL = 0;
+   ECORE_EVENT_MOUSE_IN = 0;
+   ECORE_EVENT_MOUSE_OUT = 0;
+   eina_log_domain_unregister(_ecore_input_log_dom);
+   _ecore_input_log_dom = -1;
+   return _ecore_event_init_count;
+}
+
+typedef struct _Ecore_Event_Modifier_Match Ecore_Event_Modifier_Match;
+struct _Ecore_Event_Modifier_Match
+{
+   const char *key;
+   Ecore_Event_Modifier modifier;
+   unsigned int event_modifier;
+};
+
+static const Ecore_Event_Modifier_Match matchs[] = {
+  { "Shift_L", ECORE_SHIFT, ECORE_EVENT_MODIFIER_SHIFT },
+  { "Shift_R", ECORE_SHIFT, ECORE_EVENT_MODIFIER_SHIFT },
+  { "Alt_L", ECORE_ALT, ECORE_EVENT_MODIFIER_ALT },
+  { "Alt_R", ECORE_ALT, ECORE_EVENT_MODIFIER_ALT },
+  { "Control_L", ECORE_CTRL, ECORE_EVENT_MODIFIER_CTRL },
+  { "Control_R", ECORE_CTRL, ECORE_EVENT_MODIFIER_CTRL },
+  { "Caps_Lock", ECORE_CAPS, ECORE_EVENT_MODIFIER_CAPS },
+  { "Super_L", ECORE_WIN, ECORE_EVENT_MODIFIER_WIN },
+  { "Super_R", ECORE_WIN, ECORE_EVENT_MODIFIER_WIN },
+  { "Scroll_Lock", ECORE_SCROLL, ECORE_EVENT_MODIFIER_SCROLL }
+};
+
+EAPI unsigned int
+ecore_event_modifier_mask(Ecore_Event_Modifier modifier)
+{
+   size_t i;
+
+   for (i = 0; i < sizeof (matchs) / sizeof (Ecore_Event_Modifier_Match); i++)
+     if (matchs[i].modifier == modifier)
+       return matchs[i].event_modifier;
+
+   return 0;
+}
+
+EAPI Ecore_Event_Modifier
+ecore_event_update_modifier(const char *key, Ecore_Event_Modifiers *modifiers, int inc)
+{
+   size_t i;
+
+   for (i = 0; i < sizeof (matchs) / sizeof (Ecore_Event_Modifier_Match); i++)
+     if (strcmp(matchs[i].key, key) == 0)
+       {
+         if (modifiers && matchs[i].modifier < modifiers->size)
+           modifiers->array[matchs[i].modifier] += inc;
+         return matchs[i].modifier;
+       }
+
+   return ECORE_NONE;
+}
diff --git a/src/lib/ecore_input/ecore_input_private.h b/src/lib/ecore_input/ecore_input_private.h
new file mode 100644 (file)
index 0000000..5660a20
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ECORE_INPUT_PRIVATE_H
+#define _ECORE_INPUT_PRIVATE_H
+
+extern int _ecore_input_log_dom;
+
+#ifdef ECORE_INPUT_DEFAULT_LOG_COLOR
+# undef ECORE_INPUT_DEFAULT_LOG_COLOR 
+#endif
+
+#define ECORE_INPUT_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_input_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_input_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_input_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_input_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_input_log_dom, __VA_ARGS__)
+
+#endif
diff --git a/src/lib/ecore_input_evas/Ecore_Input_Evas.h b/src/lib/ecore_input_evas/Ecore_Input_Evas.h
new file mode 100644 (file)
index 0000000..265d611
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_INPUT_EVAS_H
+#define _ECORE_INPUT_EVAS_H
+
+#include <Evas.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_INPUT_EVAS_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_INPUT_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*Ecore_Event_Mouse_Move_Cb)(void *window, int x, int y, unsigned int timestamp);
+
+EAPI int        ecore_event_evas_init(void);
+EAPI int        ecore_event_evas_shutdown(void);
+
+EAPI int        ecore_event_evas_key_down(void *data, int type, void *event);
+EAPI int        ecore_event_evas_key_up(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_button_up(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_button_down(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_wheel(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_move(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_in(void *data, int type, void *event);
+EAPI int        ecore_event_evas_mouse_out(void *data, int type, void *event);
+
+EAPI void        ecore_event_window_register(Ecore_Window id, void *window, Evas *evas, Ecore_Event_Mouse_Move_Cb move_mouse);
+EAPI void        ecore_event_window_unregister(Ecore_Window id);
+EAPI void*       ecore_event_window_match(Ecore_Window id);
+EAPI void        ecore_event_window_ignore_events(Ecore_Window id, int ignore_event);
+
+EAPI void       ecore_event_evas_modifier_lock_update(Evas *e, unsigned int modifiers);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_input_evas/Makefile.am b/src/lib/ecore_input_evas/Makefile.am
new file mode 100644 (file)
index 0000000..b0fe622
--- /dev/null
@@ -0,0 +1,32 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore_input \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore \
+@EFL_ECORE_INPUT_EVAS_BUILD@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@ \
+@EVIL_CFLAGS@
+
+if BUILD_ECORE_INPUT_EVAS
+
+lib_LTLIBRARIES = libecore_input_evas.la
+include_HEADERS = Ecore_Input_Evas.h
+
+libecore_input_evas_la_SOURCES = \
+ecore_input_evas.c
+
+libecore_input_evas_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@ \
+@EVIL_LIBS@
+
+libecore_input_evas_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_input_evas_release_info@
+
+endif
+
+EXTRA_DIST = ecore_input_evas_private.h
diff --git a/src/lib/ecore_input_evas/ecore_input_evas.c b/src/lib/ecore_input_evas/ecore_input_evas.c
new file mode 100644 (file)
index 0000000..15664da
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "Ecore.h"
+#include "Ecore_Input.h"
+
+#include "Ecore_Input_Evas.h"
+#include "ecore_input_evas_private.h"
+
+int _ecore_input_evas_log_dom = -1;
+
+typedef struct _Ecore_Input_Window Ecore_Input_Window;
+struct _Ecore_Input_Window
+{
+   Evas *evas;
+   void *window;
+   Ecore_Event_Mouse_Move_Cb move_mouse;
+   int ignore_event;
+};
+
+static int _ecore_event_evas_init_count = 0;
+static Ecore_Event_Handler *ecore_event_evas_handlers[8];
+static Eina_Hash *_window_hash = NULL;
+
+EAPI void
+ecore_event_evas_modifier_lock_update(Evas *e, unsigned int modifiers)
+{
+   if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
+     evas_key_modifier_on(e, "Shift");
+   else evas_key_modifier_off(e, "Shift");
+
+   if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
+     evas_key_modifier_on(e, "Control");
+   else evas_key_modifier_off(e, "Control");
+
+   if (modifiers & ECORE_EVENT_MODIFIER_ALT)
+     evas_key_modifier_on(e, "Alt");
+   else evas_key_modifier_off(e, "Alt");
+
+   if (modifiers & ECORE_EVENT_MODIFIER_WIN)
+     {
+       evas_key_modifier_on(e, "Super");
+       evas_key_modifier_on(e, "Hyper");
+     }
+   else
+     {
+       evas_key_modifier_off(e, "Super");
+       evas_key_modifier_off(e, "Hyper");
+     }
+
+   if (modifiers & ECORE_EVENT_LOCK_SCROLL)
+     evas_key_lock_on(e, "Scroll_Lock");
+   else evas_key_lock_off(e, "Scroll_Lock");
+
+   if (modifiers & ECORE_EVENT_LOCK_NUM)
+     evas_key_lock_on(e, "Num_Lock");
+   else evas_key_lock_off(e, "Num_Lock");
+
+   if (modifiers & ECORE_EVENT_LOCK_CAPS)
+     evas_key_lock_on(e, "Caps_Lock");
+   else evas_key_lock_off(e, "Caps_Lock");
+}
+
+EAPI void
+ecore_event_window_register(Ecore_Window id, void *window, Evas *evas, Ecore_Event_Mouse_Move_Cb move_mouse)
+{
+   Ecore_Input_Window *w;
+
+   w = calloc(1, sizeof(Ecore_Input_Window));
+   if (!w) return;
+
+   w->evas = evas;
+   w->window = window;
+   w->move_mouse = move_mouse;
+   w->ignore_event = 0;
+
+   eina_hash_add(_window_hash, &id, w);
+
+   evas_key_modifier_add(evas, "Shift");
+   evas_key_modifier_add(evas, "Control");
+   evas_key_modifier_add(evas, "Alt");
+   evas_key_modifier_add(evas, "Meta");
+   evas_key_modifier_add(evas, "Hyper");
+   evas_key_modifier_add(evas, "Super");
+   evas_key_lock_add(evas, "Caps_Lock");
+   evas_key_lock_add(evas, "Num_Lock");
+   evas_key_lock_add(evas, "Scroll_Lock");
+}
+
+EAPI void
+ecore_event_window_unregister(Ecore_Window id)
+{
+   eina_hash_del(_window_hash, &id, NULL);
+}
+
+EAPI void *
+ecore_event_window_match(Ecore_Window id)
+{
+   Ecore_Input_Window *lookup;
+
+   lookup = eina_hash_find(_window_hash, &id);
+   if (lookup) return lookup->window;
+   return NULL;
+}
+
+EAPI void
+ecore_event_window_ignore_events(Ecore_Window id, int ignore_event)
+{
+   Ecore_Input_Window *lookup;
+
+   lookup = eina_hash_find(_window_hash, &id);
+   if (!lookup) return;
+   lookup->ignore_event = ignore_event;
+}
+
+static Ecore_Input_Window*
+_ecore_event_window_match(Ecore_Window id)
+{
+   Ecore_Input_Window *lookup;
+
+   lookup = eina_hash_find(_window_hash, &id);
+   if (!lookup) return NULL;
+   if (lookup->ignore_event) return NULL; /* Pass on event. */
+   return lookup;
+}
+
+static int
+_ecore_event_evas_key(Ecore_Event_Key *e, Ecore_Event_Press press)
+{
+   Ecore_Input_Window *lookup;
+
+   lookup = _ecore_event_window_match(e->window);
+   if (!lookup) return 1;
+   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
+   if (press == ECORE_DOWN)
+     evas_event_feed_key_down(lookup->evas, e->keyname, e->key, e->string, e->compose, e->timestamp, NULL);
+   else
+     evas_event_feed_key_up(lookup->evas, e->keyname, e->key, e->string, e->compose, e->timestamp, NULL);
+   return 1;
+}
+
+static int
+_ecore_event_evas_mouse_button(Ecore_Event_Mouse_Button *e, Ecore_Event_Press press)
+{
+   Ecore_Input_Window *lookup;
+   Evas_Button_Flags flags = EVAS_BUTTON_NONE;
+
+   lookup = _ecore_event_window_match(e->window);
+   if (!lookup) return 1;
+   if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
+   if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
+   if (e->multi.device == 0)
+     {
+        ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
+        if (press == ECORE_DOWN)
+          evas_event_feed_mouse_down(lookup->evas, e->buttons, flags, e->timestamp, NULL);
+        else
+          evas_event_feed_mouse_up(lookup->evas, e->buttons, flags, e->timestamp, NULL);
+     }
+   else
+     {
+        if (press == ECORE_DOWN)
+          evas_event_feed_multi_down(lookup->evas, e->multi.device, e->x, e->y, e->multi.radius, e->multi.radius_x, e->multi.radius_y, e->multi.pressure, e->multi.angle, e->multi.x, e->multi.y, flags, e->timestamp, NULL);
+        else
+          evas_event_feed_multi_up(lookup->evas, e->multi.device, e->x, e->y, e->multi.radius, e->multi.radius_x, e->multi.radius_y, e->multi.pressure, e->multi.angle, e->multi.x, e->multi.y, flags, e->timestamp, NULL);
+     }
+   return 1;
+}
+
+EAPI int
+ecore_event_evas_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Event_Mouse_Move *e;
+   Ecore_Input_Window *lookup;
+
+   e = event;
+   lookup = _ecore_event_window_match(e->window);
+   if (!lookup) return 1;
+   if (e->multi.device == 0)
+     {
+        ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
+        lookup->move_mouse(lookup->window, e->x, e->y, e->timestamp);
+     }
+   else
+     {
+        evas_event_feed_multi_move(lookup->evas, e->multi.device, e->x, e->y, e->multi.radius, e->multi.radius_x, e->multi.radius_y, e->multi.pressure, e->multi.angle, e->multi.x, e->multi.y, e->timestamp, NULL);
+     }
+   return 1;
+}
+
+EAPI int
+ecore_event_evas_mouse_button_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_mouse_button((Ecore_Event_Mouse_Button *)event, ECORE_DOWN);
+}
+
+EAPI int
+ecore_event_evas_mouse_button_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_mouse_button((Ecore_Event_Mouse_Button *)event, ECORE_UP);
+}
+
+static int
+_ecore_event_evas_mouse_io(Ecore_Event_Mouse_IO *e, Ecore_Event_IO io)
+{
+   Ecore_Input_Window *lookup;
+
+   lookup = _ecore_event_window_match(e->window);
+   if (!lookup) return 1;
+   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
+   switch (io)
+     {
+      case ECORE_IN:
+        evas_event_feed_mouse_in(lookup->evas, e->timestamp, NULL);
+        break;
+      case ECORE_OUT:
+        evas_event_feed_mouse_out(lookup->evas, e->timestamp, NULL);
+        break;
+      default:
+        break;
+     }
+
+   lookup->move_mouse(lookup->window, e->x, e->y, e->timestamp);
+   return 1;
+}
+
+EAPI int
+ecore_event_evas_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_key((Ecore_Event_Key *)event, ECORE_DOWN);
+}
+
+EAPI int
+ecore_event_evas_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_key((Ecore_Event_Key *)event, ECORE_UP);
+}
+
+EAPI int
+ecore_event_evas_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   Ecore_Event_Mouse_Wheel *e;
+   Ecore_Input_Window *lookup;
+
+   e = event;
+   lookup = _ecore_event_window_match(e->window);
+   if (!lookup) return 1;
+   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
+   evas_event_feed_mouse_wheel(lookup->evas, e->direction, e->z, e->timestamp, NULL);
+   return 1;
+}
+
+EAPI int
+ecore_event_evas_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_mouse_io((Ecore_Event_Mouse_IO *)event, ECORE_IN);
+}
+
+EAPI int
+ecore_event_evas_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+   return _ecore_event_evas_mouse_io((Ecore_Event_Mouse_IO *)event, ECORE_OUT);
+}
+
+EAPI int
+ecore_event_evas_init(void)
+{
+   if (++_ecore_event_evas_init_count !=  1)
+     return _ecore_event_evas_init_count;
+
+   _ecore_input_evas_log_dom = eina_log_domain_register("EcoreInputEvas",  ECORE_INPUT_EVAS_DEFAULT_LOG_COLOR);
+   if (_ecore_input_evas_log_dom < 0)
+     {
+        EINA_LOG_ERR("Impossible to create a log domain for the ecore input evas_module.");
+        return --_ecore_event_evas_init_count;
+     }
+
+   if (!ecore_init())
+     {
+       return --_ecore_event_evas_init_count;
+     }
+
+   if (!ecore_event_init())
+     {
+       goto shutdown_ecore;
+     }
+
+   ecore_event_evas_handlers[0] = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
+                                                         ecore_event_evas_key_down,
+                                                         NULL);
+   ecore_event_evas_handlers[1] = ecore_event_handler_add(ECORE_EVENT_KEY_UP,
+                                                         ecore_event_evas_key_up,
+                                                         NULL);
+   ecore_event_evas_handlers[2] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
+                                                         ecore_event_evas_mouse_button_down,
+                                                         NULL);
+   ecore_event_evas_handlers[3] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
+                                                         ecore_event_evas_mouse_button_up,
+                                                         NULL);
+   ecore_event_evas_handlers[4] = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
+                                                         ecore_event_evas_mouse_move,
+                                                         NULL);
+   ecore_event_evas_handlers[5] = ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
+                                                         ecore_event_evas_mouse_wheel,
+                                                         NULL);
+   ecore_event_evas_handlers[6] = ecore_event_handler_add(ECORE_EVENT_MOUSE_IN,
+                                                         ecore_event_evas_mouse_in,
+                                                         NULL);
+   ecore_event_evas_handlers[7] = ecore_event_handler_add(ECORE_EVENT_MOUSE_OUT,
+                                                         ecore_event_evas_mouse_out,
+                                                         NULL);
+   
+   _window_hash = eina_hash_pointer_new(free);
+   
+   return _ecore_event_evas_init_count;
+   
+   shutdown_ecore:
+   ecore_shutdown();
+   
+   return --_ecore_event_evas_init_count;
+}
+
+EAPI int
+ecore_event_evas_shutdown(void)
+{
+   size_t i;
+   
+   if (--_ecore_event_evas_init_count != 0)
+     return _ecore_event_evas_init_count;
+   
+   eina_hash_free(_window_hash);
+   _window_hash = NULL;
+   for (i = 0; i < sizeof(ecore_event_evas_handlers) / sizeof(Ecore_Event_Handler *); i++)
+     {
+       ecore_event_handler_del(ecore_event_evas_handlers[i]);
+       ecore_event_evas_handlers[i] = NULL;
+     }
+   
+   ecore_event_shutdown();
+   ecore_shutdown();
+   
+   eina_log_domain_unregister(_ecore_input_evas_log_dom);
+   _ecore_input_evas_log_dom = -1;
+   
+   return _ecore_event_evas_init_count;
+}
diff --git a/src/lib/ecore_input_evas/ecore_input_evas_private.h b/src/lib/ecore_input_evas/ecore_input_evas_private.h
new file mode 100644 (file)
index 0000000..c19cfbf
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ECORE_INPUT_PRIVATE_H
+#define _ECORE_INPUT_PRIVATE_H
+
+extern int _ecore_input_evas_log_dom;
+
+#ifdef ECORE_INPUT_EVAS_DEFAULT_LOG_COLOR
+#undef ECORE_INPUT_EVAS_DEFAULT_LOG_COLOR 
+#endif
+
+#define ECORE_INPUT_EVAS_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_input_evas_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_input_evas_log_dom, __VA_ARGS__)
+
+#ifdef INF
+#undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_input_evas_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+#undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_input_evas_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+#undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_input_evas_log_dom, __VA_ARGS__)
+
+#endif
diff --git a/src/lib/ecore_ipc/.cvsignore b/src/lib/ecore_ipc/.cvsignore
new file mode 100644 (file)
index 0000000..f98e6f6
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+Ecore_Ipc.h
+Makefile
+Makefile.in
+ecore_ipc.lo
+libecore_ipc.la
diff --git a/src/lib/ecore_ipc/Ecore_Ipc.h b/src/lib/ecore_ipc/Ecore_Ipc.h
new file mode 100644 (file)
index 0000000..41392ee
--- /dev/null
@@ -0,0 +1,326 @@
+#ifndef _ECORE_IPC_H
+#define _ECORE_IPC_H
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+/**
+ * @file Ecore_Ipc.h
+ * @brief Ecore inter-process communication functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifndef _ECORE_IPC_PRIVATE_H
+   typedef void Ecore_Ipc_Server; /**< An IPC connection handle */
+   typedef void Ecore_Ipc_Client; /**< An IPC connection handle */
+#endif
+
+/**
+ * Macros used for generic data packing
+ */
+EAPI unsigned short _ecore_ipc_swap_16(unsigned short v);
+EAPI unsigned int _ecore_ipc_swap_32(unsigned int v);
+EAPI unsigned long long _ecore_ipc_swap_64(unsigned long long v);
+
+#ifdef WORDS_BIGENDIAN
+#define ECORE_IPC_SWAP2NET64(x) _ecore_ipc_swap_64(x)
+#define ECORE_IPC_SWAP2CPU64(x) _ecore_ipc_swap_64(x)
+#define ECORE_IPC_SWAP2NET32(x) _ecore_ipc_swap_32(x)
+#define ECORE_IPC_SWAP2CPU32(x) _ecore_ipc_swap_32(x)
+#define ECORE_IPC_SWAP2NET16(x) _ecore_ipc_swap_16(x)
+#define ECORE_IPC_SWAP2CPU16(x) _ecore_ipc_swap_16(x)
+#define ECORE_IPC_SWAP2NET8(x) (x)
+#define ECORE_IPC_SWAP2CPU8(x) (x)
+#else
+#define ECORE_IPC_SWAP2NET64(x) (x)
+#define ECORE_IPC_SWAP2CPU64(x) (x)
+#define ECORE_IPC_SWAP2NET32(x) (x)
+#define ECORE_IPC_SWAP2CPU32(x) (x)
+#define ECORE_IPC_SWAP2NET16(x) (x)
+#define ECORE_IPC_SWAP2CPU16(x) (x)
+#define ECORE_IPC_SWAP2NET8(x) (x)
+#define ECORE_IPC_SWAP2CPU8(x) (x)
+#endif
+
+/* 1, 2, 4 and 8 byte datatypes */
+/* unpacking */
+#define ECORE_IPC_GET64(v)\
+    { \
+       p->v = ECORE_IPC_SWAP2CPU64(*(long long *)(ptr)); \
+       ptr += 8; \
+    }
+#define ECORE_IPC_GET32(v)\
+    { \
+       p->v = ECORE_IPC_SWAP2CPU32(*(int *)(ptr)); \
+       ptr += 4; \
+    }
+#define ECORE_IPC_GET16(v)\
+    { \
+       p->v = ECORE_IPC_SWAP2CPU16(*(short *)(ptr)); \
+       ptr += 2; \
+    }
+#define ECORE_IPC_GET8(v) \
+    { \
+       p->v = ECORE_IPC_SWAP2CPU8(*(char *)(ptr)); \
+       ptr += 1; \
+    }
+/* packing */
+#define ECORE_IPC_PUT64(v)\
+    { \
+       *(long long *)(ptr) = ECORE_IPC_SWAP2NET64(p->v); \
+       ptr += 8; \
+    }
+#define ECORE_IPC_PUT32(v)\
+    { \
+       *(int *)(ptr) = ECORE_IPC_SWAP2NET32(p->v); \
+       ptr += 4; \
+    }
+#define ECORE_IPC_PUT16(v)\
+    { \
+       *(short *)(ptr) = ECORE_IPC_SWAP2NET16(p->v); \
+       ptr += 2; \
+    }
+#define ECORE_IPC_PUT8(v) \
+    { \
+       *(char *)(ptr) = ECORE_IPC_SWAP2NET8(p->v); \
+       ptr += 1; \
+    }
+/* padding data */
+#define ECORE_IPC_PAD8()   ptr += 1
+#define ECORE_IPC_PAD16()  ptr += 2
+#define ECORE_IPC_PAD32()  ptr += 4
+#define ECORE_IPC_PAD64()  ptr += 8
+
+/* counting data when encoding lists */
+#define ECORE_IPC_CNT8()    len += 1
+#define ECORE_IPC_CNT16()   len += 2
+#define ECORE_IPC_CNT32()   len += 4
+#define ECORE_IPC_CNT64()   len += 8
+
+/* strings */
+#define ECORE_IPC_CHEKS() if (*((unsigned char *)d + s - 1) != 0) return 0;
+#define ECORE_IPC_GETS(v) \
+    { \
+       if (ptr < ((unsigned char *)d + s)) \
+           { \
+               p->v = (char *)ptr; \
+               ptr += strlen(p->v) + 1; \
+           } \
+    } 
+#define ECORE_IPC_PUTS(v, l)\
+    { \
+       strcpy((char *)ptr, p->v); \
+       ptr += l + 1; \
+    }
+
+/* handy to calculate what sized block we need to alloc */
+#define ECORE_IPC_SLEN(l, v) ((l = strlen(p->v)) + 1)
+#define ECORE_IPC_CNTS(v)   len += strlen(p->v) + 1
+
+/* saves typing function headers */
+#define ECORE_IPC_DEC_STRUCT_PROTO(x) static int x(void *d, int s, void *pp)
+#define ECORE_IPC_ENC_STRUCT_PROTO(x) static void *x(void *pp, int *s)
+#define ECORE_IPC_DEC_EINA_LIST_PROTO(x) static Eina_List *x(void *d, int s)
+#define ECORE_IPC_ENC_EINA_LIST_PROTO(x) static void *x(Eina_List *lp, int *s)
+
+
+/* decoder setup - saves typing. requires data packet of exact size, or fail */
+#define ECORE_IPC_DEC_STRUCT_HEAD_EXACT(typ, x) \
+    typ *p; \
+    unsigned char *ptr; \
+    p = (typ *)pp; \
+    if (!d) return 0; if (s != (x)) return 0; \
+    ptr = d;
+/* decoder setup - saves typing. requires data packet of a minimum size */
+#define ECORE_IPC_DEC_STRUCT_HEAD_MIN(typ, x) \
+    typ *p; \
+    unsigned char *ptr; \
+    p = (typ *)pp; \
+    if (!d) return 0; if (s < (x)) return 0; \
+    ptr = d;
+/* footer for the hell of it */
+#define ECORE_IPC_DEC_STRUCT_FOOT() return 1
+/* header for encoder - gives native strct type and size of flattened packet */
+#define ECORE_IPC_ENC_STRUCT_HEAD(typ, sz) \
+    typ *p; \
+    unsigned char *d, *ptr; \
+    int len; \
+    *s = 0; \
+    if(!pp) return NULL; \
+    p = (typ *)pp; \
+    len = sz; \
+    d = malloc(len); \
+    if (!d) return NULL; \
+    *s = len; \
+    ptr = d;
+/* footer for the hell of it */
+#define ECORE_IPC_ENC_STRUCT_FOOT() return d
+
+#define ECORE_IPC_DEC_EINA_LIST_HEAD(typ) \
+    unsigned char *ptr; \
+    Eina_List *l; \
+    typ *p; \
+    l = NULL; \
+    ptr = d; \
+    while(ptr < (unsigned char *)(d + s)) \
+        { \
+            p = malloc(sizeof(typ));
+
+#define ECORE_IPC_DEC_EINA_LIST_FOOT() \
+           l = eina_list_append(l, p); \
+        } \
+    return l
+#define ECORE_IPC_ENC_EINA_LIST_HEAD_START(typ) \
+    Eina_List *l; \
+    typ *p; \
+    unsigned char *d, *ptr; \
+    int len; \
+    *s = 0; \
+    len = 0; \
+    for (l = lp; l; l = l->next) \
+      { \
+         p = l->data;
+#define ECORE_IPC_ENC_EINA_LIST_HEAD_FINISH() \
+      } \
+    d = malloc(len); \
+    if(!d) return NULL; \
+    *s = len; \
+    ptr = d; \
+    for (l = lp; l; l = l->next) \
+      { \
+         p = l->data;
+
+#define ECORE_IPC_ENC_EINA_LIST_FOOT() \
+      } \
+   return d
+
+   typedef enum _Ecore_Ipc_Type
+     {
+       ECORE_IPC_LOCAL_USER,
+         ECORE_IPC_LOCAL_SYSTEM,
+         ECORE_IPC_REMOTE_SYSTEM,
+          ECORE_IPC_USE_SSL = 16
+     } Ecore_Ipc_Type;
+   
+   typedef struct _Ecore_Ipc_Event_Client_Add  Ecore_Ipc_Event_Client_Add;
+   typedef struct _Ecore_Ipc_Event_Client_Del  Ecore_Ipc_Event_Client_Del;
+   typedef struct _Ecore_Ipc_Event_Server_Add  Ecore_Ipc_Event_Server_Add;
+   typedef struct _Ecore_Ipc_Event_Server_Del  Ecore_Ipc_Event_Server_Del;
+   typedef struct _Ecore_Ipc_Event_Client_Data Ecore_Ipc_Event_Client_Data;
+   typedef struct _Ecore_Ipc_Event_Server_Data Ecore_Ipc_Event_Server_Data;
+   
+   struct _Ecore_Ipc_Event_Client_Add
+     {
+       Ecore_Ipc_Client *client;
+     };
+   
+   struct _Ecore_Ipc_Event_Client_Del
+     {
+       Ecore_Ipc_Client *client;
+     };
+   
+   struct _Ecore_Ipc_Event_Server_Add
+     {
+       Ecore_Ipc_Server *server;
+     };
+   
+   struct _Ecore_Ipc_Event_Server_Del
+     {
+       Ecore_Ipc_Server *server;
+     };
+   
+   struct _Ecore_Ipc_Event_Client_Data
+     {
+       Ecore_Ipc_Client *client;
+       /* FIXME: this needs to become an ipc message */
+       int               major;
+       int               minor;
+       int               ref;
+       int               ref_to;
+       int               response;
+       void             *data;
+       int               size;
+     };
+   
+   struct _Ecore_Ipc_Event_Server_Data
+     {
+       Ecore_Ipc_Server *server;
+       /* FIXME: this needs to become an ipc message */
+       int               major;
+       int               minor;
+       int               ref;
+       int               ref_to;
+       int               response;
+       void             *data;
+       int               size;
+     };
+   
+   EAPI extern int ECORE_IPC_EVENT_CLIENT_ADD;
+   EAPI extern int ECORE_IPC_EVENT_CLIENT_DEL;
+   EAPI extern int ECORE_IPC_EVENT_SERVER_ADD;
+   EAPI extern int ECORE_IPC_EVENT_SERVER_DEL;
+   EAPI extern int ECORE_IPC_EVENT_CLIENT_DATA;
+   EAPI extern int ECORE_IPC_EVENT_SERVER_DATA;
+   
+   EAPI int               ecore_ipc_init(void);
+   EAPI int               ecore_ipc_shutdown(void);
+   
+   /* FIXME: need to add protocol type parameter */
+   EAPI Ecore_Ipc_Server *ecore_ipc_server_add(Ecore_Ipc_Type type, const char *name, int port, const void *data);
+   
+   /* FIXME: need to add protocol type parameter */
+   EAPI Ecore_Ipc_Server *ecore_ipc_server_connect(Ecore_Ipc_Type type, char *name, int port, const void *data);
+   EAPI void             *ecore_ipc_server_del(Ecore_Ipc_Server *svr);
+   EAPI void             *ecore_ipc_server_data_get(Ecore_Ipc_Server *svr);
+   EAPI int               ecore_ipc_server_connected_get(Ecore_Ipc_Server *svr);
+   EAPI Eina_List        *ecore_ipc_server_clients_get(Ecore_Ipc_Server *svr);
+   /* FIXME: this needs to become an ipc message */
+   EAPI int               ecore_ipc_server_send(Ecore_Ipc_Server *svr, int major, int minor, int ref, int ref_to, int response, const void *data, int size);
+   EAPI void              ecore_ipc_server_client_limit_set(Ecore_Ipc_Server *svr, int client_limit, char reject_excess_clients);
+   EAPI void              ecore_ipc_server_data_size_max_set(Ecore_Ipc_Server *srv, int size);
+   EAPI int               ecore_ipc_server_data_size_max_get(Ecore_Ipc_Server *srv);
+   EAPI char             *ecore_ipc_server_ip_get(Ecore_Ipc_Server *svr);
+   EAPI void              ecore_ipc_server_flush(Ecore_Ipc_Server *svr);
+       
+   /* FIXME: this needs to become an ipc message */
+   EAPI int               ecore_ipc_client_send(Ecore_Ipc_Client *cl, int major, int minor, int ref, int ref_to, int response, const void *data, int size);
+   EAPI Ecore_Ipc_Server *ecore_ipc_client_server_get(Ecore_Ipc_Client *cl);
+   EAPI void             *ecore_ipc_client_del(Ecore_Ipc_Client *cl);
+   EAPI void              ecore_ipc_client_data_set(Ecore_Ipc_Client *cl, const void *data);
+   EAPI void             *ecore_ipc_client_data_get(Ecore_Ipc_Client *cl);
+   EAPI void              ecore_ipc_client_data_size_max_set(Ecore_Ipc_Client *cl, int size);
+   EAPI int               ecore_ipc_client_data_size_max_get(Ecore_Ipc_Client *cl);
+   EAPI char             *ecore_ipc_client_ip_get(Ecore_Ipc_Client *cl);
+   EAPI void              ecore_ipc_client_flush(Ecore_Ipc_Client *cl);
+   
+   EAPI int               ecore_ipc_ssl_available_get(void);
+   /* FIXME: need to add a callback to "ok" large ipc messages greater than */
+   /*        a certain size (seurity/DOS attack safety) */
+   
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_ipc/Makefile.am b/src/lib/ecore_ipc/Makefile.am
new file mode 100644 (file)
index 0000000..6b3f186
--- /dev/null
@@ -0,0 +1,31 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_con \
+-I$(top_builddir)/src/lib/ecore_ipc \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_con \
+-I$(top_srcdir)/src/lib/ecore_ipc \
+@SSL_CFLAGS@ @EINA_CFLAGS@
+
+if BUILD_ECORE_IPC
+
+lib_LTLIBRARIES = libecore_ipc.la
+include_HEADERS = \
+Ecore_Ipc.h
+
+libecore_ipc_la_SOURCES = \
+ecore_ipc.c
+
+libecore_ipc_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la \
+@SSL_LIBS@ \
+@EINA_LIBS@
+
+libecore_ipc_la_LDFLAGS = -no-undefined -version-info @version_info@ @ecore_ipc_release_info@
+
+endif
+
+EXTRA_DIST = ecore_ipc_private.h
diff --git a/src/lib/ecore_ipc/ecore_ipc.c b/src/lib/ecore_ipc/ecore_ipc.c
new file mode 100644 (file)
index 0000000..5753789
--- /dev/null
@@ -0,0 +1,1588 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <sys/types.h>
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+#include "ecore_ipc_private.h"
+#include "Ecore_Ipc.h"
+
+#define DLT_ZERO   0
+#define DLT_ONE    1
+#define DLT_SAME   2
+#define DLT_SHL    3
+#define DLT_SHR    4
+#define DLT_ADD8   5
+#define DLT_DEL8   6
+#define DLT_ADDU8  7
+#define DLT_DELU8  8
+#define DLT_ADD16  9
+#define DLT_DEL16  10
+#define DLT_ADDU16 11
+#define DLT_DELU16 12
+#define DLT_SET    13
+#define DLT_R1     14
+#define DLT_R2     15
+
+int _ecore_ipc_log_dom = -1;
+
+/* byte swappers - for dealing with big vs little endian machines */
+EAPI unsigned short
+_ecore_ipc_swap_16(unsigned short v)
+{
+   unsigned char *s, t;
+
+   s = (unsigned char *)(&v);
+   t = s[0]; s[0] = s[1]; s[1] = t;
+   return v;
+}
+
+EAPI unsigned int
+_ecore_ipc_swap_32(unsigned int v)
+{
+   unsigned char *s, t;
+
+   s = (unsigned char *)(&v);
+   t = s[0]; s[0] = s[3]; s[3] = t;
+   t = s[1]; s[1] = s[2]; s[2] = t;
+   return v;
+}
+
+EAPI unsigned long long
+_ecore_ipc_swap_64(unsigned long long v)
+{
+   unsigned char *s, t;
+
+   s = (unsigned char *)(&v);
+   t = s[0]; s[0] = s[7]; s[7] = t;
+   t = s[1]; s[1] = s[6]; s[6] = t;
+   t = s[2]; s[2] = s[5]; s[5] = t;
+   t = s[3]; s[3] = s[4]; s[4] = t;
+   return v;
+}
+
+static int _ecore_ipc_dlt_int(int out, int prev, int *mode);
+static int _ecore_ipc_ddlt_int(int in, int prev, int mode);
+
+static int
+_ecore_ipc_dlt_int(int out, int prev, int *mode)
+{
+   int dlt;
+
+   /* 0 byte */
+   if (out == 0)
+     {
+       *mode = DLT_ZERO;
+       return 0;
+     }
+   if (out == (int)0xffffffff)
+     {
+       *mode = DLT_ONE;
+       return 0;
+     }
+   if (out == prev)
+     {
+       *mode = DLT_SAME;
+       return 0;
+     }
+   if (out == prev << 1)
+     {
+       *mode = DLT_SHL;
+       return 0;
+     }
+   if (out == prev >> 1)
+     {
+       *mode = DLT_SHR;
+       return 0;
+     }
+   /* 1 byte */
+   dlt = out - prev;
+   if (!(dlt & 0xffffff00))
+     {
+       *mode = DLT_ADD8;
+       return dlt & 0xff;
+     }
+   dlt = prev - out;
+   if (!(dlt & 0xffffff00))
+     {
+       *mode = DLT_DEL8;
+       return dlt & 0xff;
+     }
+   dlt = out - prev;
+   if (!(dlt & 0x00ffffff))
+     {
+       *mode = DLT_ADDU8;
+       return (dlt >> 24) & 0xff;
+     }
+   dlt = prev - out;
+   if (!(dlt & 0x00ffffff))
+     {
+       *mode = DLT_DELU8;
+       return (dlt >> 24) & 0xff;
+     }
+   /* 2 byte */
+   dlt = out - prev;
+   if (!(dlt & 0xffff0000))
+     {
+       *mode = DLT_ADD16;
+       return dlt & 0xffff;
+     }
+   dlt = prev - out;
+   if (!(dlt & 0xffff0000))
+     {
+       *mode = DLT_DEL16;
+       return dlt & 0xffff;
+     }
+   dlt = out - prev;
+   if (!(dlt & 0x0000ffff))
+     {
+       *mode = DLT_ADDU16;
+       return (dlt >> 16) & 0xffff;
+     }
+   dlt = prev - out;
+   if (!(dlt & 0x0000ffff))
+     {
+       *mode = DLT_DELU16;
+       return (dlt >> 16) & 0xffff;
+     }
+   /* 4 byte */
+   *mode = DLT_SET;
+   return out;
+}
+
+static int
+_ecore_ipc_ddlt_int(int in, int prev, int mode)
+{
+   switch (mode)
+     {
+      case DLT_ZERO:
+       return 0;
+       break;
+      case DLT_ONE:
+       return 0xffffffff;
+       break;
+      case DLT_SAME:
+       return prev;
+       break;
+      case DLT_SHL:
+       return prev << 1;
+       break;
+      case DLT_SHR:
+       return prev >> 1;
+       break;
+      case DLT_ADD8:
+       return prev + in;
+       break;
+      case DLT_DEL8:
+       return prev - in;
+       break;
+      case DLT_ADDU8:
+       return prev + (in << 24);
+       break;
+      case DLT_DELU8:
+       return prev - (in << 24);
+       break;
+      case DLT_ADD16:
+       return prev + in;
+       break;
+      case DLT_DEL16:
+       return prev - in;
+       break;
+      case DLT_ADDU16:
+       return prev + (in << 16);
+       break;
+      case DLT_DELU16:
+       return prev - (in << 16);
+       break;
+      case DLT_SET:
+       return in;
+       break;
+      case DLT_R1:
+       return 0;
+       break;
+      case DLT_R2:
+       return 0;
+       break;
+      default:
+       break;
+     }
+   return 0;
+}
+
+static int _ecore_ipc_event_client_add(void *data, int ev_type, void *ev);
+static int _ecore_ipc_event_client_del(void *data, int ev_type, void *ev);
+static int _ecore_ipc_event_server_add(void *data, int ev_type, void *ev);
+static int _ecore_ipc_event_server_del(void *data, int ev_type, void *ev);
+static int _ecore_ipc_event_client_data(void *data, int ev_type, void *ev);
+static int _ecore_ipc_event_server_data(void *data, int ev_type, void *ev);
+static void _ecore_ipc_event_client_add_free(void *data, void *ev);
+static void _ecore_ipc_event_client_del_free(void *data, void *ev);
+static void _ecore_ipc_event_client_data_free(void *data, void *ev);
+static void _ecore_ipc_event_server_add_free(void *data, void *ev);
+static void _ecore_ipc_event_server_del_free(void *data, void *ev);
+static void _ecore_ipc_event_server_data_free(void *data, void *ev);
+
+EAPI int ECORE_IPC_EVENT_CLIENT_ADD = 0;
+EAPI int ECORE_IPC_EVENT_CLIENT_DEL = 0;
+EAPI int ECORE_IPC_EVENT_SERVER_ADD = 0;
+EAPI int ECORE_IPC_EVENT_SERVER_DEL = 0;
+EAPI int ECORE_IPC_EVENT_CLIENT_DATA = 0;
+EAPI int ECORE_IPC_EVENT_SERVER_DATA = 0;
+
+static int                  _ecore_ipc_init_count = 0;
+static Eina_List           *servers = NULL;
+static Ecore_Event_Handler *handler[6];
+
+/**
+ * @defgroup Ecore_IPC_Library_Group IPC Library Functions
+ *
+ * Functions that set up and shut down the Ecore IPC Library.
+ */
+
+/**
+ * Initialises the Ecore IPC library.
+ * @return  Number of times the library has been initialised without
+ *          being shut down.
+ * @ingroup Ecore_IPC_Library_Group
+ */
+EAPI int
+ecore_ipc_init(void)
+{
+   int i = 0;
+
+   if (++_ecore_ipc_init_count != 1)
+     return _ecore_ipc_init_count;
+   _ecore_ipc_log_dom = eina_log_domain_register("EcoreIpc", ECORE_IPC_DEFAULT_LOG_COLOR);
+   if(_ecore_ipc_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the Ecore IPC module.");
+       return --_ecore_ipc_init_count;
+     }
+   if (!ecore_con_init())
+     return --_ecore_ipc_init_count;
+
+   ECORE_IPC_EVENT_CLIENT_ADD = ecore_event_type_new();
+   ECORE_IPC_EVENT_CLIENT_DEL = ecore_event_type_new();
+   ECORE_IPC_EVENT_SERVER_ADD = ecore_event_type_new();
+   ECORE_IPC_EVENT_SERVER_DEL = ecore_event_type_new();
+   ECORE_IPC_EVENT_CLIENT_DATA = ecore_event_type_new();
+   ECORE_IPC_EVENT_SERVER_DATA = ecore_event_type_new();
+
+   handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD,
+                                         _ecore_ipc_event_client_add, NULL);
+   handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL,
+                                         _ecore_ipc_event_client_del, NULL);
+   handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
+                                         _ecore_ipc_event_server_add, NULL);
+   handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
+                                         _ecore_ipc_event_server_del, NULL);
+   handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA,
+                                         _ecore_ipc_event_client_data, NULL);
+   handler[i] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
+                                         _ecore_ipc_event_server_data, NULL);
+   return _ecore_ipc_init_count;
+}
+
+/**
+ * Shuts down the Ecore IPC library.
+ * @return  Number of times the library has been initialised without being
+ *          shut down.
+ * @ingroup Ecore_IPC_Library_Group
+ */
+EAPI int
+ecore_ipc_shutdown(void)
+{
+   int i;
+
+   if (--_ecore_ipc_init_count != 0)
+     return _ecore_ipc_init_count;
+
+   while (servers) ecore_ipc_server_del(eina_list_data_get(servers));
+
+   for (i = 0; i < 6; i++)
+     ecore_event_handler_del(handler[i]);
+
+   ecore_con_shutdown();
+   eina_log_domain_unregister(_ecore_ipc_log_dom);
+   _ecore_ipc_log_dom = -1;
+   return _ecore_ipc_init_count;
+}
+
+/**
+ * @defgroup Ecore_IPC_Server_Group IPC Server Functions
+ *
+ * Functions the deal with IPC server objects.
+ */
+
+/**
+ * Creates an IPC server that listens for connections.
+ *
+ * For more details about the @p compl_type, @p name and @p port
+ * parameters, see the @ref ecore_con_server_add documentation.
+ *
+ * @param   compl_type The connection type.
+ * @param   name       Name to associate with the socket used for connection.
+ * @param   port       Number to identify with socket used for connection.
+ * @param   data       Data to associate with the IPC server.
+ * @return  New IPC server.  If there is an error, @c NULL is returned.
+ * @ingroup Ecore_IPC_Server_Group
+ * @todo    Need to add protocol type parameter to this function.
+ */
+EAPI Ecore_Ipc_Server *
+ecore_ipc_server_add(Ecore_Ipc_Type compl_type, const char *name, int port, const void *data)
+{
+   Ecore_Ipc_Server *svr;
+   Ecore_Ipc_Type type;
+   Ecore_Con_Type extra = 0;
+
+   svr = calloc(1, sizeof(Ecore_Ipc_Server));
+   if (!svr) return NULL;
+   type = compl_type;
+   type &= ~ECORE_IPC_USE_SSL;
+   if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL;
+   switch (type)
+     {
+      case ECORE_IPC_LOCAL_USER:
+       svr->server = ecore_con_server_add(ECORE_CON_LOCAL_USER | extra, name, port, svr);
+       break;
+      case ECORE_IPC_LOCAL_SYSTEM:
+       svr->server = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr);
+       break;
+      case ECORE_IPC_REMOTE_SYSTEM:
+       svr->server = ecore_con_server_add(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr);
+       break;
+      default:
+       free(svr);
+       return NULL;
+     }
+   if (!svr->server)
+     {
+       free(svr);
+       return NULL;
+     }
+   svr->max_buf_size = 32 * 1024;
+   svr->data = (void *)data;
+   servers = eina_list_append(servers, svr);
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER);
+   return svr;
+}
+
+/**
+ * Creates an IPC server object to represent the IPC server listening
+ * on the given port.
+ *
+ * For more details about the @p compl_type, @p name and @p port
+ * parameters, see the @ref ecore_con_server_connect documentation.
+ *
+ * @param   compl_type The IPC connection type.
+ * @param   name       Name used to determine which socket to use for the
+ *                     IPC connection.
+ * @param   port       Number used to identify the socket to use for the
+ *                     IPC connection.
+ * @param   data       Data to associate with the server.
+ * @return  A new IPC server.  @c NULL is returned on error.
+ * @ingroup Ecore_IPC_Server_Group
+ * @todo    Need to add protocol type parameter.
+ */
+EAPI Ecore_Ipc_Server *
+ecore_ipc_server_connect(Ecore_Ipc_Type compl_type, char *name, int port, const void *data)
+{
+   Ecore_Ipc_Server *svr;
+   Ecore_Ipc_Type type;
+   Ecore_Con_Type extra = 0;
+
+   svr = calloc(1, sizeof(Ecore_Ipc_Server));
+   if (!svr) return NULL;
+   type = compl_type;
+   type &= ~ECORE_IPC_USE_SSL;
+   if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL;
+   switch (type)
+     {
+      case ECORE_IPC_LOCAL_USER:
+       svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_USER | extra, name, port, svr);
+       break;
+      case ECORE_IPC_LOCAL_SYSTEM:
+       svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr);
+       break;
+      case ECORE_IPC_REMOTE_SYSTEM:
+       svr->server = ecore_con_server_connect(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr);
+       break;
+      default:
+       free(svr);
+       return NULL;
+     }
+   if (!svr->server)
+     {
+       free(svr);
+       return NULL;
+     }
+   svr->max_buf_size = -1;
+   svr->data = (void *)data;
+   servers = eina_list_append(servers, svr);
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER);
+   return svr;
+}
+
+/**
+ * Closes the connection and frees the given IPC server.
+ * @param   svr The given IPC server.
+ * @return  The data associated with the server when it was created.
+ * @ingroup Ecore_IPC_Server_Group
+ */
+EAPI void *
+ecore_ipc_server_del(Ecore_Ipc_Server *svr)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_del");
+       return NULL;
+     }
+   if (svr->delete_me) return NULL;
+
+   data = svr->data;
+   svr->data = NULL;
+   svr->delete_me = 1;
+   if (svr->event_count == 0)
+     {
+       Ecore_Ipc_Client *cl;
+
+       EINA_LIST_FREE(svr->clients, cl)
+         ecore_ipc_client_del(cl);
+       ecore_con_server_del(svr->server);
+       servers = eina_list_remove(servers, svr);
+
+       if (svr->buf) free(svr->buf);
+       ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE);
+       free(svr);
+     }
+   return data;
+}
+
+/**
+ * Retrieves the data associated with the given IPC server.
+ * @param   svr The given IPC server.
+ * @return  The associated data.
+ * @ingroup Ecore_IPC_Server_Group
+ */
+EAPI void *
+ecore_ipc_server_data_get(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_data_get");
+       return NULL;
+     }
+   return svr->data;
+}
+
+/**
+ * Retrieves whether the given IPC server is currently connected.
+ * @param   svr The given IPC server.
+ * @return  @c 1 if the server is connected.  @c 0 otherwise.
+ * @ingroup Ecore_IPC_Server_Group
+ */
+EAPI int
+ecore_ipc_server_connected_get(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_connected_get");
+       return 0;
+     }
+   return ecore_con_server_connected_get(svr->server);
+}
+
+/**
+ * Retrieves the list of clients for this server.
+ * @param   svr The given IPC server.
+ * @return  An Eina_List with the clients.
+ * @ingroup Ecore_IPC_Server_Group
+ */
+EAPI Eina_List *
+ecore_ipc_server_clients_get(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_clients_get");
+       return NULL;
+     }
+   return svr->client_list;
+}
+
+#define SVENC(_member) \
+   d = _ecore_ipc_dlt_int(msg._member, svr->prev.o._member, &md); \
+   if (md >= DLT_SET) \
+     { \
+       unsigned int v; \
+       unsigned char *dd; \
+       dd = (unsigned char *)&v; \
+       v = d; \
+       v = htonl(v); \
+       *(dat + s + 0) = dd[0]; \
+       *(dat + s + 1) = dd[1]; \
+       *(dat + s + 2) = dd[2]; \
+       *(dat + s + 3) = dd[3]; \
+       s += 4; \
+     } \
+   else if (md >= DLT_ADD16) \
+     { \
+       unsigned short v; \
+       unsigned char *dd; \
+       dd = (unsigned char *)&v; \
+       v = d; \
+       v = htons(v); \
+       *(dat + s + 0) = dd[0]; \
+       *(dat + s + 1) = dd[1]; \
+       s += 2; \
+     } \
+   else if (md >= DLT_ADD8) \
+     { \
+       *(dat + s + 0) = (unsigned char)d; \
+       s += 1; \
+     }
+
+/**
+ * Sends a message to the given IPC server.
+ *
+ * The content of the parameters, excluding the @p svr paramter, is up to
+ * the client.
+ *
+ * @param   svr      The given IPC server.
+ * @param   major    Major opcode of the message.
+ * @param   minor    Minor opcode of the message.
+ * @param   ref      Message reference number.
+ * @param   ref_to   Reference number of the message this message refers to.
+ * @param   response Requires response.
+ * @param   data     The data to send as part of the message.
+ * @param   size     Length of the data, in bytes, to send.
+ * @return  Number of bytes sent.  @c 0 is returned if there is an error.
+ * @ingroup Ecore_IPC_Server_Group
+ * @todo    This function needs to become an IPC message.
+ * @todo Fix up the documentation: Make sure what ref_to and response are.
+ */
+EAPI int
+ecore_ipc_server_send(Ecore_Ipc_Server *svr, int major, int minor, int ref, int ref_to, int response, const void *data, int size)
+{
+   Ecore_Ipc_Msg_Head msg;
+   int ret;
+   int *head, md = 0, d, s;
+   unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)];
+
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_send");
+       return 0;
+     }
+   if (size < 0) size = 0;
+   msg.major    = major;
+   msg.minor    = minor;
+   msg.ref      = ref;
+   msg.ref_to   = ref_to;
+   msg.response = response;
+   msg.size     = size;
+   head = (int *)dat;
+   s = 4;
+   SVENC(major);
+   *head = md;
+   SVENC(minor);
+   *head |= md << (4 * 1);
+   SVENC(ref);
+   *head |= md << (4 * 2);
+   SVENC(ref_to);
+   *head |= md << (4 * 3);
+   SVENC(response);
+   *head |= md << (4 * 4);
+   SVENC(size);
+   *head |= md << (4 * 5);
+   *head = htonl(*head);
+   svr->prev.o = msg;
+   ret = ecore_con_server_send(svr->server, dat, s);
+   if (size > 0) ret += ecore_con_server_send(svr->server, data, size);
+   return ret;
+}
+
+/**
+ * Sets a limit on the number of clients that can be handled concurrently
+ * by the given server, and a policy on what to do if excess clients try to
+ * connect.
+ * Beware that if you set this once ecore is already running, you may
+ * already have pending CLIENT_ADD events in your event queue.  Those
+ * clients have already connected and will not be affected by this call.
+ * Only clients subsequently trying to connect will be affected.
+ * @param   svr           The given server.
+ * @param   client_limit  The maximum number of clients to handle
+ *                        concurrently.  -1 means unlimited (default).  0
+ *                        effectively disables the server.
+ * @param   reject_excess_clients  Set to 1 to automatically disconnect
+ *                        excess clients as soon as they connect if you are
+ *                        already handling client_limit clients.  Set to 0
+ *                        (default) to just hold off on the "accept()"
+ *                        system call until the number of active clients
+ *                        drops. This causes the kernel to queue up to 4096
+ *                        connections (or your kernel's limit, whichever is
+ *                        lower).
+ * @ingroup Ecore_Ipc_Server_Group
+ */
+EAPI void
+ecore_ipc_server_client_limit_set(Ecore_Ipc_Server *svr, int client_limit, char reject_excess_clients)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_client_limit_set");
+       return;
+     }
+   ecore_con_server_client_limit_set(svr->server, client_limit, reject_excess_clients);
+}
+
+/**
+ * Sets the max data payload size for an Ipc message in bytes
+ *
+ * @param   svr           The given server.
+ * @param   size          The maximum data payload size in bytes.
+ * @ingroup Ecore_Ipc_Server_Group
+ */
+EAPI void
+ecore_ipc_server_data_size_max_set(Ecore_Ipc_Server *svr, int size)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_data_size_max_set");
+       return;
+     }
+   svr->max_buf_size = size;
+}
+
+/**
+ * Gets the max data payload size for an Ipc message in bytes
+ *
+ * @param   svr           The given server.
+ * @return The maximum data payload in bytes.
+ * @ingroup Ecore_Ipc_Server_Group
+ */
+EAPI int
+ecore_ipc_server_data_size_max_get(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_data_size_max_get");
+       return -1;
+     }
+   return svr->max_buf_size;
+}
+
+/**
+ * Gets the IP address of a server that has been connected to.
+ *
+ * @param   svr           The given server.
+ * @return  A pointer to an internal string that contains the IP address of
+ *          the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
+ *          This string should not be modified or trusted to stay valid after
+ *          deletion for the @p svr object. If no IP is known NULL is returned.
+ * @ingroup Ecore_Ipc_Server_Group
+ */
+EAPI char *
+ecore_ipc_server_ip_get(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_ip_get");
+       return NULL;
+     }
+   return ecore_con_server_ip_get(svr->server);
+}
+
+/**
+ * Flushes all pending data to the given server. Will return when done.
+ *
+ * @param   svr           The given server.
+ * @ingroup Ecore_Ipc_Server_Group
+ */
+EAPI void
+ecore_ipc_server_flush(Ecore_Ipc_Server *svr)
+{
+   if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
+     {
+       ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
+                        "ecore_ipc_server_server_flush");
+       return;
+     }
+   ecore_con_server_flush(svr->server);
+}
+
+#define CLENC(_member) \
+   d = _ecore_ipc_dlt_int(msg._member, cl->prev.o._member, &md); \
+   if (md >= DLT_SET) \
+     { \
+       unsigned int v; \
+       unsigned char *dd; \
+       dd = (unsigned char *)&v; \
+       v = d; \
+       v = htonl(v); \
+       *(dat + s + 0) = dd[0]; \
+       *(dat + s + 1) = dd[1]; \
+       *(dat + s + 2) = dd[2]; \
+       *(dat + s + 3) = dd[3]; \
+       s += 4; \
+     } \
+   else if (md >= DLT_ADD16) \
+     { \
+       unsigned short v; \
+       unsigned char *dd; \
+       dd = (unsigned char *)&v; \
+       v = d; \
+       v = htons(v); \
+       *(dat + s + 0) = dd[0]; \
+       *(dat + s + 1) = dd[1]; \
+       s += 2; \
+     } \
+   else if (md >= DLT_ADD8) \
+     { \
+       *(dat + s) = (unsigned char)d; \
+       s += 1; \
+     }
+
+/**
+ * @defgroup Ecore_IPC_Client_Group IPC Client Functions
+ *
+ * Functions that deal with IPC client objects.
+ */
+
+/**
+ * Sends a message to the given IPC client.
+ * @param   cl       The given IPC client.
+ * @param   major    Major opcode of the message.
+ * @param   minor    Minor opcode of the message.
+ * @param   ref      Reference number of the message.
+ * @param   ref_to   Reference number of the message this message refers to.
+ * @param   response Requires response.
+ * @param   data     The data to send as part of the message.
+ * @param   size     Length of the data, in bytes, to send.
+ * @return  The number of bytes sent.  @c 0 will be returned if there is
+ *          an error.
+ * @ingroup Ecore_IPC_Client_Group
+ * @todo    This function needs to become an IPC message.
+ * @todo    Make sure ref_to and response parameters are described correctly.
+ */
+EAPI int
+ecore_ipc_client_send(Ecore_Ipc_Client *cl, int major, int minor, int ref, int ref_to, int response, const void *data, int size)
+{
+   Ecore_Ipc_Msg_Head msg;
+   int ret;
+   int *head, md = 0, d, s;
+   unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)];
+
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_send");
+       return 0;
+     }
+   if (size < 0) size = 0;
+   msg.major    = major;
+   msg.minor    = minor;
+   msg.ref      = ref;
+   msg.ref_to   = ref_to;
+   msg.response = response;
+   msg.size     = size;
+   head = (int *)dat;
+   s = 4;
+   CLENC(major);
+   *head = md;
+   CLENC(minor);
+   *head |= md << (4 * 1);
+   CLENC(ref);
+   *head |= md << (4 * 2);
+   CLENC(ref_to);
+   *head |= md << (4 * 3);
+   CLENC(response);
+   *head |= md << (4 * 4);
+   CLENC(size);
+   *head |= md << (4 * 5);
+   *head = htonl(*head);
+   cl->prev.o = msg;
+   ret = ecore_con_client_send(cl->client, dat, s);
+   if (size > 0) ret += ecore_con_client_send(cl->client, data, size);
+   return ret;
+}
+
+/**
+ * Retrieves the IPC server that the given IPC client is connected to.
+ * @param   cl The given IPC client.
+ * @return  The IPC server the IPC client is connected to.
+ * @ingroup Ecore_IPC_Client_Group
+ */
+EAPI Ecore_Ipc_Server *
+ecore_ipc_client_server_get(Ecore_Ipc_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_server_get");
+       return NULL;
+     }
+   return (ecore_con_server_data_get(ecore_con_client_server_get(cl->client)));
+}
+
+/**
+ * Closes the connection and frees memory allocated to the given IPC
+ * client.
+ * @param   cl The given client.
+ * @return  Data associated with the client.
+ * @ingroup Ecore_IPC_Client_Group
+ */
+EAPI void *
+ecore_ipc_client_del(Ecore_Ipc_Client *cl)
+{
+   void *data;
+   Ecore_Ipc_Server *svr;
+
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_del");
+       return NULL;
+     }
+   data = cl->data;
+   cl->data = NULL;
+   cl->delete_me = 1;
+   if (cl->event_count == 0)
+     {
+       svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client));
+       ecore_con_client_del(cl->client);
+       svr->clients = eina_list_remove(svr->clients, cl);
+       if (cl->buf) free(cl->buf);
+       ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE);
+       free(cl);
+     }
+   return data;
+}
+
+/**
+ * Sets the IPC data associated with the given IPC client to @p data.
+ * @param   cl   The given IPC client.
+ * @param   data The data to associate with the IPC client.
+ * @ingroup Ecore_IPC_Client_Group
+ */
+EAPI void
+ecore_ipc_client_data_set(Ecore_Ipc_Client *cl, const void *data)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_data_set");
+       return;
+     }
+   cl->data = (void *)data;
+}
+
+/**
+ * Retrieves the data that has been associated with the given IPC client.
+ * @param   cl The given client.
+ * @return  The data associated with the IPC client.
+ * @ingroup Ecore_IPC_Client_Group
+ */
+EAPI void *
+ecore_ipc_client_data_get(Ecore_Ipc_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_data_get");
+       return NULL;
+     }
+   return cl->data;
+}
+
+/**
+ * Sets the max data payload size for an Ipc message in bytes
+ *
+ * @param   client        The given client.
+ * @param   size          The maximum data payload size in bytes.
+ * @ingroup Ecore_Ipc_Client_Group
+ */
+EAPI void
+ecore_ipc_client_data_size_max_set(Ecore_Ipc_Client *cl, int size)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_data_size_max_set");
+       return;
+     }
+   cl->max_buf_size = size;
+}
+
+/**
+ * Sets the max data payload size for an Ipc message in bytes
+ *
+ * @param   cl            The given client.
+ * @param   size          The maximum data payload size in bytes.
+ * @ingroup Ecore_Ipc_Client_Group
+ */
+EAPI int
+ecore_ipc_client_data_size_max_get(Ecore_Ipc_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_data_size_max_get");
+       return -1;
+     }
+   return cl->max_buf_size;
+}
+
+/**
+ * Gets the IP address of a client that has been connected to.
+ *
+ * @param   cl            The given client.
+ * @return  A pointer to an internal string that contains the IP address of
+ *          the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
+ *          This string should not be modified or trusted to stay valid after
+ *          deletion for the @p cl object. If no IP is known NULL is returned.
+ * @ingroup Ecore_Ipc_Client_Group
+ */
+EAPI char *
+ecore_ipc_client_ip_get(Ecore_Ipc_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_ip_get");
+       return NULL;
+     }
+   return ecore_con_client_ip_get(cl->client);
+}
+
+/**
+ * Flushes all pending data to the given client. Will return when done.
+ *
+ * @param   cl            The given client.
+ * @ingroup Ecore_Ipc_Client_Group
+ */
+EAPI void
+ecore_ipc_client_flush(Ecore_Ipc_Client *cl)
+{
+   if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
+     {
+       ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
+                        "ecore_ipc_client_flush");
+       return;
+     }
+   ecore_con_client_flush(cl->client);
+}
+
+/**
+ * Returns if SSL support is available
+ * @return  1 if SSL is available, 0 if it is not.
+ * @ingroup Ecore_Con_Client_Group
+ */
+EAPI int
+ecore_ipc_ssl_available_get(void)
+{
+   return ecore_con_ssl_available_get();
+}
+
+
+static int
+_ecore_ipc_event_client_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Add *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Client *cl;
+       Ecore_Ipc_Server *svr;
+
+       cl = calloc(1, sizeof(Ecore_Ipc_Client));
+       if (!cl) return 0;
+       svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client));
+       ECORE_MAGIC_SET(cl, ECORE_MAGIC_IPC_CLIENT);
+       cl->client = e->client;
+       cl->max_buf_size = 32 * 1024;
+       ecore_con_client_data_set(cl->client, (void *)cl);
+       svr->clients = eina_list_append(svr->clients, cl);
+       svr->client_list = eina_list_append(svr->client_list, cl);
+       if (!cl->delete_me)
+         {
+            Ecore_Ipc_Event_Client_Add *e2;
+
+            e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Add));
+            if (e2)
+              {
+                  cl->event_count++;
+                 e2->client = cl;
+                 ecore_event_add(ECORE_IPC_EVENT_CLIENT_ADD, e2,
+                                 _ecore_ipc_event_client_add_free, NULL);
+              }
+         }
+     }
+   return 0;
+}
+
+static int
+_ecore_ipc_event_client_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Del *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Client *cl;
+
+       cl = ecore_con_client_data_get(e->client);
+         {
+            Ecore_Ipc_Event_Client_Del *e2;
+            Ecore_Ipc_Server *svr;
+
+            svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client));
+            svr->client_list = eina_list_remove(svr->client_list, cl);
+            if (!cl->delete_me)
+              {
+                 e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Del));
+                 if (e2)
+                   {
+                      cl->event_count++;
+                      e2->client = cl;
+                      ecore_event_add(ECORE_IPC_EVENT_CLIENT_DEL, e2,
+                                      _ecore_ipc_event_client_del_free, NULL);
+                   }
+              }
+         }
+     }
+   return 0;
+}
+
+static int
+_ecore_ipc_event_server_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Add *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Server *svr;
+
+       svr = ecore_con_server_data_get(e->server);
+       if (!svr->delete_me)
+         {
+            Ecore_Ipc_Event_Server_Add *e2;
+
+            e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Add));
+            if (e2)
+              {
+                  svr->event_count++;
+                 e2->server = svr;
+                 ecore_event_add(ECORE_IPC_EVENT_SERVER_ADD, e2,
+                                 _ecore_ipc_event_server_add_free, NULL);
+              }
+         }
+     }
+   return 0;
+}
+
+static int
+_ecore_ipc_event_server_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Del *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Server *svr;
+
+       svr = ecore_con_server_data_get(e->server);
+       if (!svr->delete_me)
+         {
+            Ecore_Ipc_Event_Server_Del *e2;
+
+            e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Del));
+            if (e2)
+              {
+                  svr->event_count++;
+                 e2->server = svr;
+                 ecore_event_add(ECORE_IPC_EVENT_SERVER_DEL, e2,
+                                 _ecore_ipc_event_server_del_free, NULL);
+              }
+         }
+     }
+   return 0;
+}
+
+#define CLSZ(_n) \
+   md = ((head >> (4 * _n)) & 0xf); \
+   if (md >= DLT_SET) s += 4; \
+   else if (md >= DLT_ADD16) s += 2; \
+   else if (md >= DLT_ADD8) s += 1;
+
+#define CLDEC(_n, _member) \
+   md = ((head >> (4 * _n)) & 0xf); \
+   if (md >= DLT_SET) \
+     { \
+       unsigned int v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(cl->buf + offset + s + 0); \
+       dv[1] = *(cl->buf + offset + s + 1); \
+       dv[2] = *(cl->buf + offset + s + 2); \
+       dv[3] = *(cl->buf + offset + s + 3); \
+       d = (int)ntohl(v); \
+       s += 4; \
+     } \
+   else if (md >= DLT_ADD16) \
+     { \
+       unsigned short v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(cl->buf + offset + s + 0); \
+       dv[1] = *(cl->buf + offset + s + 1); \
+       d = (int)ntohs(v); \
+       s += 2; \
+     } \
+   else if (md >= DLT_ADD8) \
+     { \
+       unsigned char v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(cl->buf + offset + s + 0); \
+       d = (int)v; \
+       s += 1; \
+     } \
+   msg._member = _ecore_ipc_ddlt_int(d, cl->prev.i._member, md);
+
+static int
+_ecore_ipc_event_client_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Client_Data *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Client *cl;
+       Ecore_Ipc_Msg_Head msg;
+       int offset = 0;
+       unsigned char *buf;
+
+       cl = ecore_con_client_data_get(e->client);
+
+       if (!cl->buf)
+         {
+            cl->buf_size = e->size;
+            cl->buf = e->data;
+            e->data = NULL; /* take it out of the old event */
+         }
+       else
+         {
+            buf = realloc(cl->buf, cl->buf_size + e->size);
+            if (!buf)
+              {
+                 free(cl->buf);
+                 cl->buf = 0;
+                 cl->buf_size  = 0;
+                 return 0;
+              }
+            cl->buf = buf;
+            memcpy(cl->buf + cl->buf_size, e->data, e->size);
+            cl->buf_size += e->size;
+         }
+       /* examine header */
+       redo:
+       if ((cl->buf_size - offset) >= (int)sizeof(int))
+         {
+            int s, md, d = 0, head;
+            unsigned char *dd;
+
+            dd = (unsigned char *)&head;
+            dd[0] = *(cl->buf + offset + 0);
+            dd[1] = *(cl->buf + offset + 1);
+            dd[2] = *(cl->buf + offset + 2);
+            dd[3] = *(cl->buf + offset + 3);
+            head = ntohl(head);
+            dd = (unsigned char *)&d;
+            s = 4;
+            CLSZ(0);
+            CLSZ(1);
+            CLSZ(2);
+            CLSZ(3);
+            CLSZ(4);
+            CLSZ(5);
+            if ((cl->buf_size - offset) < s)
+              {
+                 if (offset > 0) goto scroll;
+                 return 0;
+              }
+
+            s = 4;
+            CLDEC(0, major);
+            CLDEC(1, minor);
+            CLDEC(2, ref);
+            CLDEC(3, ref_to);
+            CLDEC(4, response);
+            CLDEC(5, size);
+            if (msg.size < 0) msg.size = 0;
+            /* there is enough data in the buffer for a full message */
+            if ((cl->buf_size - offset) >= (s + msg.size))
+              {
+                 Ecore_Ipc_Event_Client_Data *e2;
+                 Ecore_Ipc_Server *svr;
+                 int max, max2;
+
+                 buf = NULL;
+                 svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client));
+                 max = svr->max_buf_size;
+                 max2 = cl->max_buf_size;
+                 if ((max >= 0) && (max2 >= 0))
+                   {
+                      if (max2 < max) max = max2;
+                   }
+                 else
+                   {
+                      if (max < 0) max = max2;
+                   }
+                 if ((max < 0) || (msg.size <= max))
+                   {
+                      if (msg.size > 0)
+                        {
+                           buf = malloc(msg.size);
+                           if (!buf) return 0;
+                           memcpy(buf, cl->buf + offset + s, msg.size);
+                        }
+                      if (!cl->delete_me)
+                        {
+                           e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Data));
+                           if (e2)
+                             {
+                                cl->event_count++;
+                                e2->client   = cl;
+                                e2->major    = msg.major;
+                                e2->minor    = msg.minor;
+                                e2->ref      = msg.ref;
+                                e2->ref_to   = msg.ref_to;
+                                e2->response = msg.response;
+                                e2->size     = msg.size;
+                                e2->data     = buf;
+                                ecore_event_add(ECORE_IPC_EVENT_CLIENT_DATA, e2,
+                                                _ecore_ipc_event_client_data_free,
+                                                NULL);
+                             }
+                        }
+                   }
+                 cl->prev.i = msg;
+                 offset += (s + msg.size);
+                 if (cl->buf_size == offset)
+                   {
+                      free(cl->buf);
+                      cl->buf = NULL;
+                      cl->buf_size = 0;
+                      return 0;
+                   }
+                 goto redo;
+              }
+            else goto scroll;
+         }
+       else
+         {
+            scroll:
+            buf = malloc(cl->buf_size - offset);
+            if (!buf)
+              {
+                 free(cl->buf);
+                 cl->buf = NULL;
+                 cl->buf_size = 0;
+                 return 0;
+              }
+            memcpy(buf, cl->buf + offset, cl->buf_size - offset);
+            free(cl->buf);
+            cl->buf = buf;
+            cl->buf_size -= offset;
+         }
+     }
+   return 0;
+}
+
+#define SVSZ(_n) \
+   md = ((head >> (4 * _n)) & 0xf); \
+   if (md >= DLT_SET) s += 4; \
+   else if (md >= DLT_ADD16) s += 2; \
+   else if (md >= DLT_ADD8) s += 1;
+
+#define SVDEC(_n, _member) \
+   md = ((head >> (4 * _n)) & 0xf); \
+   if (md >= DLT_SET) \
+     { \
+       unsigned int v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(svr->buf + offset + s + 0); \
+       dv[1] = *(svr->buf + offset + s + 1); \
+       dv[2] = *(svr->buf + offset + s + 2); \
+       dv[3] = *(svr->buf + offset + s + 3); \
+       d = (int)ntohl(v); \
+       s += 4; \
+     } \
+   else if (md >= DLT_ADD16) \
+     { \
+       unsigned short v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(svr->buf + offset + s + 0); \
+       dv[1] = *(svr->buf + offset + s + 1); \
+       d = (int)ntohs(v); \
+       s += 2; \
+     } \
+   else if (md >= DLT_ADD8) \
+     { \
+       unsigned char v; \
+       unsigned char *dv; \
+       dv = (unsigned char *)&v; \
+       dv[0] = *(svr->buf + offset + s + 0); \
+       d = (int)v; \
+       s += 1; \
+     } \
+   msg._member = _ecore_ipc_ddlt_int(d, svr->prev.i._member, md);
+
+static int
+_ecore_ipc_event_server_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
+{
+   Ecore_Con_Event_Server_Data *e;
+
+   e = ev;
+   if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
+   /* handling code here */
+     {
+       Ecore_Ipc_Server *svr;
+       Ecore_Ipc_Msg_Head msg;
+       int offset = 0;
+       unsigned char *buf;
+
+       svr = ecore_con_server_data_get(e->server);
+
+       if (!svr->buf)
+         {
+            svr->buf_size = e->size;
+            svr->buf = e->data;
+            e->data = NULL; /* take it out of the old event */
+         }
+       else
+         {
+            buf = realloc(svr->buf, svr->buf_size + e->size);
+            if (!buf)
+              {
+                 free(svr->buf);
+                 svr->buf = 0;
+                 svr->buf_size  = 0;
+                 return 0;
+              }
+            svr->buf = buf;
+            memcpy(svr->buf + svr->buf_size, e->data, e->size);
+            svr->buf_size += e->size;
+         }
+       /* examine header */
+       redo:
+       if ((svr->buf_size - offset) >= (int)sizeof(int))
+         {
+            int s, md, d = 0, head;
+            unsigned char *dd;
+
+            dd = (unsigned char *)&head;
+            dd[0] = *(svr->buf + offset + 0);
+            dd[1] = *(svr->buf + offset + 1);
+            dd[2] = *(svr->buf + offset + 2);
+            dd[3] = *(svr->buf + offset + 3);
+            head = ntohl(head);
+            dd = (unsigned char *)&d;
+            s = 4;
+            SVSZ(0);
+            SVSZ(1);
+            SVSZ(2);
+            SVSZ(3);
+            SVSZ(4);
+            SVSZ(5);
+            if ((svr->buf_size - offset) < s)
+              {
+                 if (offset > 0) goto scroll;
+                 return 0;
+              }
+
+            s = 4;
+            SVDEC(0, major);
+            SVDEC(1, minor);
+            SVDEC(2, ref);
+            SVDEC(3, ref_to);
+            SVDEC(4, response);
+            SVDEC(5, size);
+            if (msg.size < 0) msg.size = 0;
+            /* there is enough data in the buffer for a full message */
+            if ((svr->buf_size - offset) >= (s + msg.size))
+              {
+                 Ecore_Ipc_Event_Server_Data *e2;
+                 int max;
+
+                 buf = NULL;
+                 max = svr->max_buf_size;
+                 if ((max < 0) || (msg.size <= max))
+                   {
+                      if (msg.size > 0)
+                        {
+                           buf = malloc(msg.size);
+                           if (!buf) return 0;
+                           memcpy(buf, svr->buf + offset + s, msg.size);
+                        }
+                      if (!svr->delete_me)
+                        {
+                           e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Data));
+                           if (e2)
+                             {
+                                svr->event_count++;
+                                e2->server   = svr;
+                                e2->major    = msg.major;
+                                e2->minor    = msg.minor;
+                                e2->ref      = msg.ref;
+                                e2->ref_to   = msg.ref_to;
+                                e2->response = msg.response;
+                                e2->size     = msg.size;
+                                e2->data     = buf;
+                                ecore_event_add(ECORE_IPC_EVENT_SERVER_DATA, e2,
+                                                _ecore_ipc_event_server_data_free,
+                                                NULL);
+                             }
+                        }
+                   }
+                 svr->prev.i = msg;
+                 offset += (s + msg.size);
+                 if (svr->buf_size == offset)
+                   {
+                      free(svr->buf);
+                      svr->buf = NULL;
+                      svr->buf_size = 0;
+                      return 0;
+                   }
+                 goto redo;
+              }
+            else goto scroll;
+         }
+       else
+         {
+            scroll:
+            buf = malloc(svr->buf_size - offset);
+            if (!buf)
+              {
+                 free(svr->buf);
+                 svr->buf = NULL;
+                 svr->buf_size = 0;
+                 return 0;
+              }
+            memcpy(buf, svr->buf + offset, svr->buf_size - offset);
+            free(svr->buf);
+            svr->buf = buf;
+            svr->buf_size -= offset;
+         }
+     }
+   return 0;
+}
+
+static void
+_ecore_ipc_event_client_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Client_Add *e;
+
+   e = ev;
+   e->client->event_count--;
+   if ((e->client->event_count == 0) && (e->client->delete_me))
+     ecore_ipc_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_ipc_event_client_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Client_Del *e;
+
+   e = ev;
+   e->client->event_count--;
+   if ((e->client->event_count == 0) && (e->client->delete_me))
+     ecore_ipc_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_ipc_event_client_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Client_Data *e;
+
+   e = ev;
+   e->client->event_count--;
+   if (e->data) free(e->data);
+   if ((e->client->event_count == 0) && (e->client->delete_me))
+     ecore_ipc_client_del(e->client);
+   free(e);
+}
+
+static void
+_ecore_ipc_event_server_add_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Server_Add *e;
+
+   e = ev;
+   e->server->event_count--;
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     ecore_ipc_server_del(e->server);
+   free(e);
+}
+
+static void
+_ecore_ipc_event_server_del_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Server_Add *e;
+
+   e = ev;
+   e->server->event_count--;
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     ecore_ipc_server_del(e->server);
+   free(e);
+}
+
+static void
+_ecore_ipc_event_server_data_free(void *data __UNUSED__, void *ev)
+{
+   Ecore_Ipc_Event_Server_Data *e;
+
+   e = ev;
+   if (e->data) free(e->data);
+   e->server->event_count--;
+   if ((e->server->event_count == 0) && (e->server->delete_me))
+     ecore_ipc_server_del(e->server);
+   free(e);
+}
diff --git a/src/lib/ecore_ipc/ecore_ipc_private.h b/src/lib/ecore_ipc/ecore_ipc_private.h
new file mode 100644 (file)
index 0000000..b46f62b
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef _ECORE_IPC_PRIVATE_H
+#define _ECORE_IPC_PRIVATE_H
+
+
+extern int _ecore_ipc_log_dom;
+
+#ifdef ECORE_IPC_DEFAULT_LOG_COLOR
+# undef ECORE_IPC_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_IPC_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_ipc_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_ipc_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_ipc_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_ipc_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_ipc_log_dom, __VA_ARGS__)
+
+#if USE_GNUTLS_OPENSSL
+# include <gnutls/openssl.h>
+#elif USE_OPENSSL
+# include <openssl/ssl.h>
+#endif
+
+#define ECORE_MAGIC_IPC_SERVER             0x87786556
+#define ECORE_MAGIC_IPC_CLIENT             0x78875665
+
+typedef struct _Ecore_Ipc_Client Ecore_Ipc_Client;
+typedef struct _Ecore_Ipc_Server Ecore_Ipc_Server;
+typedef struct _Ecore_Ipc_Msg_Head Ecore_Ipc_Msg_Head;
+
+
+#ifdef __sgi
+#pragma pack 4
+#endif
+struct _Ecore_Ipc_Msg_Head
+{
+      int major;
+      int minor;
+      int ref;
+      int ref_to;
+      int response;
+      int size;
+} 
+#ifdef _GNU_C_
+__attribute__ ((packed));
+#endif
+;
+#ifdef __sgi
+#pragma pack 0
+#endif
+
+struct _Ecore_Ipc_Client
+{
+   ECORE_MAGIC;
+   Ecore_Con_Client  *client;
+   void              *data;
+   unsigned char     *buf;
+   int                buf_size;
+   int                max_buf_size;
+   
+   struct {
+      Ecore_Ipc_Msg_Head i, o;
+   } prev;
+   
+   int               event_count;
+   char              delete_me : 1;
+};
+   
+struct _Ecore_Ipc_Server
+{
+   ECORE_MAGIC;
+   Ecore_Con_Server *server;
+   Eina_List        *clients;
+   Eina_List        *client_list;
+   void              *data;
+   unsigned char     *buf;
+   int                buf_size;
+   int                max_buf_size;
+
+   struct {
+      Ecore_Ipc_Msg_Head i, o;
+   } prev;
+   
+   int               event_count;
+   char              delete_me : 1;
+};
+
+#endif
diff --git a/src/lib/ecore_sdl/.cvsignore b/src/lib/ecore_sdl/.cvsignore
new file mode 100644 (file)
index 0000000..09980ae
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/ecore_sdl/Ecore_Sdl.h b/src/lib/ecore_sdl/Ecore_Sdl.h
new file mode 100644 (file)
index 0000000..ea81358
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_SDL_H
+#define _ECORE_SDL_H
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_SDL_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_SDL_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file
+ * @brief Ecore SDL system functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EAPI extern int ECORE_SDL_EVENT_KEY_DOWN; /**< SDL Key Down event */
+EAPI extern int ECORE_SDL_EVENT_KEY_UP; /**< SDL Key Up event */
+EAPI extern int ECORE_SDL_EVENT_MOUSE_BUTTON_DOWN; /**< SDL Mouse Down event */
+EAPI extern int ECORE_SDL_EVENT_MOUSE_BUTTON_UP; /**< SDL Mouse Up event */
+EAPI extern int ECORE_SDL_EVENT_MOUSE_MOVE; /**< SDL Mouse Move event */
+EAPI extern int ECORE_SDL_EVENT_MOUSE_WHEEL; /**< SDL Mouse Wheel event */
+EAPI extern int ECORE_SDL_EVENT_GOT_FOCUS; /**< SDL Mouse Wheel event */
+EAPI extern int ECORE_SDL_EVENT_LOST_FOCUS; /**< SDL Mouse Wheel event */
+EAPI extern int ECORE_SDL_EVENT_RESIZE;
+EAPI extern int ECORE_SDL_EVENT_EXPOSE;
+
+typedef struct _Ecore_Sdl_Event_Key_Down Ecore_Sdl_Event_Key_Down;
+struct _Ecore_Sdl_Event_Key_Down /** SDL Key Down event */
+{
+        const char      *keyname; /**< The name of the key that was pressed */
+        const char      *keycompose; /**< The UTF-8 string conversion if any */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Key_Up Ecore_Sdl_Event_Key_Up;
+struct _Ecore_Sdl_Event_Key_Up /** SDL Key Up event */
+{
+        const char      *keyname; /**< The name of the key that was released */
+        const char      *keycompose; /**< The UTF-8 string conversion if any */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Mouse_Button_Down Ecore_Sdl_Event_Mouse_Button_Down;
+struct _Ecore_Sdl_Event_Mouse_Button_Down /** SDL Mouse Down event */
+{
+       int             button; /**< Mouse button that was pressed (1 - 32) */
+       int             x; /**< Mouse co-ordinates when mouse button was pressed */
+       int             y; /**< Mouse co-ordinates when mouse button was pressed */
+       int             double_click : 1; /**< Set if click was a double click */
+       int             triple_click : 1; /**< Set if click was a triple click  */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Mouse_Button_Up Ecore_Sdl_Event_Mouse_Button_Up;
+struct _Ecore_Sdl_Event_Mouse_Button_Up /** SDL Mouse Up event */
+{
+       int             button; /**< Mouse button that was released (1 - 32) */
+       int             x; /**< Mouse co-ordinates when mouse button was raised */
+       int             y; /**< Mouse co-ordinates when mouse button was raised */
+       int             double_click : 1; /**< Set if click was a double click */
+       int             triple_click : 1; /**< Set if click was a triple click  */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Mouse_Move Ecore_Sdl_Event_Mouse_Move;
+struct _Ecore_Sdl_Event_Mouse_Move /** SDL Mouse Move event */ 
+{
+       int             x; /**< Mouse co-ordinates where the mouse cursor moved to */
+       int             y; /**< Mouse co-ordinates where the mouse cursor moved to */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Mouse_Wheel Ecore_Sdl_Event_Mouse_Wheel;
+struct _Ecore_Sdl_Event_Mouse_Wheel /** SDL Mouse Wheel event */
+{
+       int             x,y;
+       int             direction; /* 0 = vertical, 1 = horizontal */
+       int             wheel; /* value 1 (left/up), -1 (right/down) */
+        unsigned int    time;
+};
+
+typedef struct _Ecore_Sdl_Event_Video_Resize Ecore_Sdl_Event_Video_Resize;
+struct _Ecore_Sdl_Event_Video_Resize
+{
+        int             w;
+        int             h;
+};
+
+EAPI int        ecore_sdl_init(const char *name);
+EAPI int        ecore_sdl_shutdown(void);
+EAPI void       ecore_sdl_feed_events(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_sdl/Ecore_Sdl_Keys.h b/src/lib/ecore_sdl/Ecore_Sdl_Keys.h
new file mode 100644 (file)
index 0000000..e1bc430
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef         ECORE_SDL_KEYS_H__
+# define        ECORE_SDL_KEYS_H__
+
+struct _ecore_sdl_keys_s
+{
+   int          code;
+   const char*  name;
+   const char*  compose;
+};
+
+static const struct _ecore_sdl_keys_s  keystable[] =
+{
+   { SDLK_UNKNOWN,      "0x00",         "" },
+   { SDLK_FIRST,        "First",        "First" },
+   { SDLK_BACKSPACE,    "BackSpace",    "\010" },
+   { SDLK_TAB,          "Tab",          "\011" },
+   { SDLK_CLEAR,        "Clear",        "Clear" },
+   { SDLK_RETURN,       "Return",       "\015" },
+   { SDLK_PAUSE,        "Pause",        "Pause" },
+   { SDLK_ESCAPE,       "Escape",       "\033" },
+   { SDLK_SPACE,        "space",        " " },
+   { SDLK_EXCLAIM,      "exclam",       "!" },
+   { SDLK_QUOTEDBL,     "quotedbl",     "\"" },
+   { SDLK_HASH,         "numbersign",   "#" },
+   { SDLK_DOLLAR,       "dollar",       "$" },
+   { SDLK_AMPERSAND,    "ampersand",    "&" },
+   { SDLK_QUOTE,        "apostrophe",   "'" },
+   { SDLK_LEFTPAREN,    "parenleft",    "(" },
+   { SDLK_RIGHTPAREN,   "parenright",   ")" },
+   { SDLK_ASTERISK,     "asterik",      "*" },
+   { SDLK_PLUS,         "plus",         "+" },
+   { SDLK_COMMA,        "comma",        "," },
+   { SDLK_MINUS,        "minus",        "-" },
+   { SDLK_PERIOD,       "period",       "." },
+   { SDLK_SLASH,        "slash",        "/" },
+   { SDLK_0,            "0",            "0" },
+   { SDLK_1,            "1",            "1" },
+   { SDLK_2,            "2",            "2" },
+   { SDLK_3,            "3",            "3" },
+   { SDLK_4,            "4",            "4" },
+   { SDLK_5,            "5",            "5" },
+   { SDLK_6,            "6",            "6" },
+   { SDLK_7,            "7",            "7" },
+   { SDLK_8,            "8",            "8" },
+   { SDLK_9,            "9",            "9" },
+   { SDLK_COLON,        "colon",        ":" },
+   { SDLK_SEMICOLON,    "semicolon",    ";" },
+   { SDLK_LESS,         "less",         "<" },
+   { SDLK_EQUALS,       "equal",        "=" },
+   { SDLK_GREATER,      "greater",      ">" },
+   { SDLK_QUESTION,     "question",     "?" },
+   { SDLK_AT,           "at",           "@" },
+
+   /* Skip uppercase letters */
+   { SDLK_LEFTBRACKET,  "bracketleft",  "[" },
+   { SDLK_BACKSLASH,    "backslash",    "\\" },
+   { SDLK_RIGHTBRACKET, "bracketright", "]" },
+   { SDLK_CARET,        "asciicircumm", "^" },
+   { SDLK_UNDERSCORE,   "underscore",   "_" },
+   { SDLK_BACKQUOTE,    "asciitilde",   "`" },
+   { SDLK_a,            "a",            "a" },
+   { SDLK_b,            "b",            "b" },
+   { SDLK_c,            "c",            "c" },
+   { SDLK_d,            "d",            "d" },
+   { SDLK_e,            "e",            "e" },
+   { SDLK_f,            "f",            "f" },
+   { SDLK_g,            "g",            "g" },
+   { SDLK_h,            "h",            "h" },
+   { SDLK_i,            "i",            "i" },
+   { SDLK_j,            "j",            "j" },
+   { SDLK_k,            "k",            "k" },
+   { SDLK_l,            "l",            "l" },
+   { SDLK_m,            "m",            "m" },
+   { SDLK_n,            "n",            "n" },
+   { SDLK_o,            "o",            "o" },
+   { SDLK_p,            "p",            "p" },
+   { SDLK_q,            "q",            "q" },
+   { SDLK_r,            "r",            "r" },
+   { SDLK_s,            "s",            "s" },
+   { SDLK_t,            "t",            "t" },
+   { SDLK_u,            "u",            "u" },
+   { SDLK_v,            "v",            "v" },
+   { SDLK_w,            "w",            "w" },
+   { SDLK_x,            "x",            "x" },
+   { SDLK_y,            "y",            "y" },
+   { SDLK_z,            "z",            "z" },
+   { SDLK_DELETE,       "Delete",       "\177" },
+   /* End of ASCII mapped keysyms */
+
+   /* International keyboard syms */
+   { SDLK_WORLD_0,      "w0",           "" }, /* 0xA0 */
+   { SDLK_WORLD_1,      "w1",           "" },
+   { SDLK_WORLD_2,      "w2",           "" },
+   { SDLK_WORLD_3,      "w3",           "" },
+   { SDLK_WORLD_4,      "w4",           "" },
+   { SDLK_WORLD_5,      "w5",           "" },
+   { SDLK_WORLD_6,      "w6",           "" },
+   { SDLK_WORLD_7,      "w7",           "" },
+   { SDLK_WORLD_8,      "w8",           "" },
+   { SDLK_WORLD_9,      "w9",           "" },
+   { SDLK_WORLD_10,     "w10",          "" },
+   { SDLK_WORLD_11,     "w11",          "" },
+   { SDLK_WORLD_12,     "w12",          "" },
+   { SDLK_WORLD_13,     "w13",          "" },
+   { SDLK_WORLD_14,     "w14",          "" },
+   { SDLK_WORLD_15,     "w15",          "" },
+   { SDLK_WORLD_16,     "w16",          "" },
+   { SDLK_WORLD_17,     "w17",          "" },
+   { SDLK_WORLD_18,     "w18",          "" },
+   { SDLK_WORLD_19,     "w19",          "" },
+   { SDLK_WORLD_20,     "w20",          "" },
+   { SDLK_WORLD_21,     "w21",          "" },
+   { SDLK_WORLD_22,     "w22",          "" },
+   { SDLK_WORLD_23,     "w23",          "" },
+   { SDLK_WORLD_24,     "w24",          "" },
+   { SDLK_WORLD_25,     "w25",          "" },
+   { SDLK_WORLD_26,     "w26",          "" },
+   { SDLK_WORLD_27,     "w27",          "" },
+   { SDLK_WORLD_28,     "w28",          "" },
+   { SDLK_WORLD_29,     "w29",          "" },
+   { SDLK_WORLD_30,     "w30",          "" },
+   { SDLK_WORLD_31,     "w31",          "" },
+   { SDLK_WORLD_32,     "w32",          "" },
+   { SDLK_WORLD_33,     "w33",          "" },
+   { SDLK_WORLD_34,     "w34",          "" },
+   { SDLK_WORLD_35,     "w35",          "" },
+   { SDLK_WORLD_36,     "w36",          "" },
+   { SDLK_WORLD_37,     "w37",          "" },
+   { SDLK_WORLD_38,     "w38",          "" },
+   { SDLK_WORLD_39,     "w39",          "" },
+   { SDLK_WORLD_40,     "w40",          "" },
+   { SDLK_WORLD_41,     "w41",          "" },
+   { SDLK_WORLD_42,     "w42",          "" },
+   { SDLK_WORLD_43,     "w43",          "" },
+   { SDLK_WORLD_44,     "w44",          "" },
+   { SDLK_WORLD_45,     "w45",          "" },
+   { SDLK_WORLD_46,     "w46",          "" },
+   { SDLK_WORLD_47,     "w47",          "" },
+   { SDLK_WORLD_48,     "w48",          "" },
+   { SDLK_WORLD_49,     "w49",          "" },
+   { SDLK_WORLD_50,     "w50",          "" },
+   { SDLK_WORLD_51,     "w51",          "" },
+   { SDLK_WORLD_52,     "w52",          "" },
+   { SDLK_WORLD_53,     "w53",          "" },
+   { SDLK_WORLD_54,     "w54",          "" },
+   { SDLK_WORLD_55,     "w55",          "" },
+   { SDLK_WORLD_56,     "w56",          "" },
+   { SDLK_WORLD_57,     "w57",          "" },
+   { SDLK_WORLD_58,     "w58",          "" },
+   { SDLK_WORLD_59,     "w59",          "" },
+   { SDLK_WORLD_60,     "w60",          "" },
+   { SDLK_WORLD_61,     "w61",          "" },
+   { SDLK_WORLD_62,     "w62",          "" },
+   { SDLK_WORLD_63,     "w63",          "" },
+   { SDLK_WORLD_64,     "w64",          "" },
+   { SDLK_WORLD_65,     "w65",          "" },
+   { SDLK_WORLD_66,     "w66",          "" },
+   { SDLK_WORLD_67,     "w67",          "" },
+   { SDLK_WORLD_68,     "w68",          "" },
+   { SDLK_WORLD_69,     "w69",          "" },
+   { SDLK_WORLD_70,     "w70",          "" },
+   { SDLK_WORLD_71,     "w71",          "" },
+   { SDLK_WORLD_72,     "w72",          "" },
+   { SDLK_WORLD_73,     "w73",          "" },
+   { SDLK_WORLD_74,     "w74",          "" },
+   { SDLK_WORLD_75,     "w75",          "" },
+   { SDLK_WORLD_76,     "w76",          "" },
+   { SDLK_WORLD_77,     "w77",          "" },
+   { SDLK_WORLD_78,     "w78",          "" },
+   { SDLK_WORLD_79,     "w79",          "" },
+   { SDLK_WORLD_80,     "w80",          "" },
+   { SDLK_WORLD_81,     "w81",          "" },
+   { SDLK_WORLD_82,     "w82",          "" },
+   { SDLK_WORLD_83,     "w83",          "" },
+   { SDLK_WORLD_84,     "w84",          "" },
+   { SDLK_WORLD_85,     "w85",          "" },
+   { SDLK_WORLD_86,     "w86",          "" },
+   { SDLK_WORLD_87,     "w87",          "" },
+   { SDLK_WORLD_88,     "w88",          "" },
+   { SDLK_WORLD_89,     "w89",          "" },
+   { SDLK_WORLD_90,     "w90",          "" },
+   { SDLK_WORLD_91,     "w91",          "" },
+   { SDLK_WORLD_92,     "w92",          "" },
+   { SDLK_WORLD_93,     "w93",          "" },
+   { SDLK_WORLD_94,     "w94",          "" },
+   { SDLK_WORLD_95,     "w95",          "" },
+
+   /* Numeric keypad */
+   { SDLK_KP0,          "KP0",          "0" },
+   { SDLK_KP1,          "KP1",          "1" },
+   { SDLK_KP2,          "KP2",          "2" },
+   { SDLK_KP3,          "KP3",          "3" },
+   { SDLK_KP4,          "KP4",          "4" },
+   { SDLK_KP5,          "KP5",          "5" },
+   { SDLK_KP6,          "KP6",          "6" },
+   { SDLK_KP7,          "KP7",          "7" },
+   { SDLK_KP8,          "KP8",          "8" },
+   { SDLK_KP9,          "KP9",          "9" },
+   { SDLK_KP_PERIOD,    "period",       "." },
+   { SDLK_KP_DIVIDE,    "KP_Divide",    "/" },
+   { SDLK_KP_MULTIPLY,  "KP_Multiply",  "*" },
+   { SDLK_KP_MINUS,     "KP_Minus",     "-" },
+   { SDLK_KP_PLUS,      "KP_Plus",      "+" },
+   { SDLK_KP_ENTER,     "KP_Enter",     "\015" },
+   { SDLK_KP_EQUALS,    "KP_Equals",    "=" },
+
+   /* Arrows + Home/End pad */
+   { SDLK_UP,           "Up",           "Up" },
+   { SDLK_DOWN,         "Down",         "Down" },
+   { SDLK_RIGHT,        "Right",        "Right" },
+   { SDLK_LEFT,         "Left",         "Left" },
+   { SDLK_INSERT,       "Insert",       "Insert" },
+   { SDLK_HOME,         "Home",         "Home" },
+   { SDLK_END,          "End",          "End" },
+   { SDLK_PAGEUP,       "Page_Up",      "Page_Up" },
+   { SDLK_PAGEDOWN,     "Page_Down",    "Page_Down" },
+
+   /* Function keys */
+   { SDLK_F1,           "F1",           "F1" },
+   { SDLK_F2,           "F2",           "F2" },
+   { SDLK_F3,           "F3",           "F3" },
+   { SDLK_F4,           "F4",           "F4" },
+   { SDLK_F5,           "F5",           "F5" },
+   { SDLK_F6,           "F6",           "F6" },
+   { SDLK_F7,           "F7",           "F7" },
+   { SDLK_F8,           "F8",           "F8" },
+   { SDLK_F9,           "F9",           "F9" },
+   { SDLK_F10,          "F10",          "F10" },
+   { SDLK_F11,          "F11",          "F11" },
+   { SDLK_F12,          "F12",          "F12" },
+   { SDLK_F13,          "F13",          "F13" },
+   { SDLK_F14,          "F14",          "F14" },
+   { SDLK_F15,          "F15",          "F15" },
+
+   /* Key state modifier keys */
+   { SDLK_NUMLOCK,      "Num_Lock",     "Num_Lock" },
+   { SDLK_CAPSLOCK,     "Caps_Lock",    "Caps_Lock" },
+   { SDLK_SCROLLOCK,    "Scroll_Lock",  "Scroll_Lock" },
+   { SDLK_RSHIFT,       "Shift_R",      "Shift_R" },
+   { SDLK_LSHIFT,       "Shift_L",      "Shift_L" },
+   { SDLK_RCTRL,        "Control_R",    "Control_R" },
+   { SDLK_LCTRL,        "Control_L",    "Control_L" },
+   { SDLK_RALT,         "Alt_R",        "Alt_R" },
+   { SDLK_LALT,         "Alt_L",        "Alt_L" },
+   { SDLK_RMETA,        "Meta_R",       "Meta_R" },
+   { SDLK_LMETA,        "Meta_L",       "Meta_L" },
+   { SDLK_LSUPER,       "Super_L",      "Super_L" },   /* Left "Windows" key */
+   { SDLK_RSUPER,       "Super_R",      "Super_R" },   /* Right "Windows" key */
+   { SDLK_MODE,         "Mode",         "Mode" },   /* "Alt Gr" key */
+   { SDLK_COMPOSE,      "Compose",      "Compose" },   /* Multi-key compose key */
+
+   /* Miscellaneous function keys */
+   { SDLK_HELP,         "Help",         "Help" },
+   { SDLK_PRINT,        "Print",        "Print" },
+   { SDLK_SYSREQ,       "SysReq",       "SysReq" },
+   { SDLK_BREAK,        "Break",        "Break" },
+   { SDLK_MENU,         "Menu",         "Menu" },
+   { SDLK_POWER,        "Power",        "Power" },   /* Power Macintosh power key */
+   { SDLK_EURO,         "Euro",         "\200" },   /* Some european keyboards */
+   { SDLK_UNDO,         "Undo",         "Undo" }    /* Atari keyboard has Undo */
+};
+
+#endif  /* ECORE_SDL_KEYS_H__ */
diff --git a/src/lib/ecore_sdl/Makefile.am b/src/lib/ecore_sdl/Makefile.am
new file mode 100644 (file)
index 0000000..2e434ef
--- /dev/null
@@ -0,0 +1,33 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_evas \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_evas \
+-I$(top_builddir)/src/lib/ecore_input \
+@EFL_ECORE_SDL_BUILD@ \
+@SDL_CFLAGS@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+if BUILD_ECORE_SDL
+
+lib_LTLIBRARIES = libecore_sdl.la
+include_HEADERS = \
+Ecore_Sdl.h
+
+libecore_sdl_la_SOURCES = \
+ecore_sdl.c
+
+libecore_sdl_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@SDL_LIBS@ @EVIL_LIBS@ @EINA_LIBS@
+
+libecore_sdl_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_sdl_release_info@
+
+endif
+
+EXTRA_DIST = Ecore_Sdl_Keys.h ecore_sdl_private.h
diff --git a/src/lib/ecore_sdl/ecore_sdl.c b/src/lib/ecore_sdl/ecore_sdl.c
new file mode 100644 (file)
index 0000000..fc98c99
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <SDL/SDL.h>
+
+#include "Eina.h"
+#include "Ecore_Sdl.h"
+#include "Ecore_Input.h"
+#include "Ecore.h"
+#include "ecore_sdl_private.h"
+#include "ecore_private.h"
+#include "Ecore_Sdl_Keys.h"
+
+#include <eina_rbtree.h>
+
+int _ecore_sdl_log_dom = -1;
+
+typedef struct _Ecore_SDL_Pressed Ecore_SDL_Pressed;
+struct _Ecore_SDL_Pressed
+{
+   EINA_RBTREE;
+
+   SDLKey key;
+};
+
+EAPI int ECORE_SDL_EVENT_GOT_FOCUS = 0;
+EAPI int ECORE_SDL_EVENT_LOST_FOCUS = 0;
+EAPI int ECORE_SDL_EVENT_RESIZE = 0;
+EAPI int ECORE_SDL_EVENT_EXPOSE = 0;
+
+static int _ecore_sdl_init_count = 0;
+static Eina_Rbtree *repeat = NULL;
+
+static Eina_Rbtree_Direction
+_ecore_sdl_pressed_key(const Ecore_SDL_Pressed *left,
+                      const Ecore_SDL_Pressed *right,
+                      __UNUSED__ void *data)
+{
+   return left->key < right->key ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
+}
+
+static int
+_ecore_sdl_pressed_node(const Ecore_SDL_Pressed *node,
+                       const SDLKey *key,
+                       __UNUSED__ int length,
+                       __UNUSED__ void *data)
+{
+   return node->key - *key;
+}
+
+/**
+ * @defgroup Ecore_Sdl_Library_Group Framebuffer Library Functions
+ *
+ * Functions used to set up and shut down the Ecore_Framebuffer functions.
+ */
+
+/**
+ * Sets up the Ecore_Sdl library.
+ * @param   name device target name
+ * @return  @c 0 on failure.  Otherwise, the number of times the library has
+ *          been initialised without being shut down.
+ * @ingroup Ecore_SDL_Library_Group
+ */
+EAPI int
+ecore_sdl_init(const char *name __UNUSED__)
+{
+   if(++_ecore_sdl_init_count != 1)
+     return _ecore_sdl_init_count;
+   _ecore_sdl_log_dom = eina_log_domain_register("EcoreSdl", ECORE_SDL_DEFAULT_LOG_COLOR);
+   if(_ecore_sdl_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the Ecore SDL module.");
+       return --_ecore_sdl_init_count;
+     }
+   if (!ecore_event_init())
+     return --_ecore_sdl_init_count;
+
+   ECORE_SDL_EVENT_GOT_FOCUS  = ecore_event_type_new();
+   ECORE_SDL_EVENT_LOST_FOCUS = ecore_event_type_new();
+   ECORE_SDL_EVENT_RESIZE     = ecore_event_type_new();
+   ECORE_SDL_EVENT_EXPOSE     = ecore_event_type_new();
+
+   SDL_EnableKeyRepeat(200, 100);
+
+   return _ecore_sdl_init_count;
+}
+
+/**
+ * Shuts down the Ecore_Sdl library.
+ * @return  @c The number of times the system has been initialised without
+ *             being shut down.
+ * @ingroup Ecore_SDL_Library_Group
+ */
+EAPI int
+ecore_sdl_shutdown(void)
+{
+   if (--_ecore_sdl_init_count != 0);
+   return _ecore_sdl_init_count;
+
+   ecore_event_shutdown();
+   eina_log_domain_unregister(_ecore_sdl_log_dom);
+   _ecore_sdl_log_dom = -1;
+   return _ecore_sdl_init_count;
+}
+
+static unsigned int
+_ecore_sdl_event_modifiers(int mod)
+{
+   unsigned int        modifiers = 0;
+
+   if(mod & KMOD_LSHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+   if(mod & KMOD_RSHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+   if(mod & KMOD_LCTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+   if(mod & KMOD_RCTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+   if(mod & KMOD_LALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
+   if(mod & KMOD_RALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
+   if(mod & KMOD_NUM) modifiers |= ECORE_EVENT_LOCK_NUM;
+   if(mod & KMOD_CAPS) modifiers |= ECORE_EVENT_LOCK_CAPS;
+
+   return modifiers;
+}
+
+static Ecore_Event_Key*
+_ecore_sdl_event_key(SDL_Event *event, double time)
+{
+   Ecore_Event_Key *ev;
+   unsigned int i;
+
+   ev = malloc(sizeof(Ecore_Event_Key));
+   if (!ev) return NULL;
+
+   ev->timestamp = time;
+   ev->window = 0;
+   ev->modifiers = _ecore_sdl_event_modifiers(SDL_GetModState());
+   ev->key = NULL;
+   ev->compose = NULL;
+
+   for (i = 0; i < sizeof(keystable) / sizeof(struct _ecore_sdl_keys_s); ++i)
+     if (keystable[i].code == event->key.keysym.sym)
+       {
+         ev->keyname = keystable[i].name;
+         ev->string = keystable[i].compose;
+
+         return ev;
+       }
+
+   free(ev);
+   return NULL;
+}
+
+EAPI void
+ecore_sdl_feed_events(void)
+{
+   SDL_Event    event;
+   unsigned int time;
+
+   while(SDL_PollEvent(&event))
+     {
+        time = (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff);
+        switch(event.type)
+          {
+          case SDL_MOUSEMOTION:
+          {
+            Ecore_Event_Mouse_Move *ev;
+
+            ev = malloc(sizeof(Ecore_Event_Mouse_Move));
+            if (!ev) return ;
+
+            ev->timestamp = time;
+            ev->window = 0;
+            ev->modifiers = 0; /* FIXME: keep modifier around. */
+             ev->x = event.motion.x;
+             ev->y = event.motion.y;
+            ev->root.x = ev->x;
+            ev->root.y = ev->y;
+
+             ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+             break;
+          }
+          case SDL_MOUSEBUTTONDOWN:
+          {
+             if (event.button.button == SDL_BUTTON_WHEELUP ||
+                 event.button.button == SDL_BUTTON_WHEELDOWN)
+               {
+                  Ecore_Event_Mouse_Wheel *ev;
+
+                  ev = malloc(sizeof(Ecore_Event_Mouse_Wheel));
+                 if (!ev) return ;
+
+                 ev->timestamp = time;
+                 ev->window = 0;
+                 ev->modifiers = 0; /* FIXME: keep modifier around. */
+                  ev->direction = 0;
+                  ev->z = event.button.button == SDL_BUTTON_WHEELDOWN ? -1 : 1;
+
+                  ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
+               }
+             else
+               {
+                  Ecore_Event_Mouse_Button *ev;
+
+                  ev = malloc(sizeof(Ecore_Event_Mouse_Button));
+                 if (!ev) return ;
+
+                 ev->timestamp = time;
+                 ev->window = 0;
+                 ev->modifiers = 0; /* FIXME: keep modifier around. */
+                  ev->buttons = event.button.button;
+                  ev->double_click = 0;
+                  ev->triple_click = 0;
+
+                  ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
+               }
+             break;
+          }
+          case SDL_MOUSEBUTTONUP:
+          {
+             Ecore_Event_Mouse_Button *ev;
+
+             ev = malloc(sizeof(Ecore_Event_Mouse_Button));
+            if (!ev) return ;
+            ev->timestamp = time;
+            ev->window = 0;
+            ev->modifiers = 0; /* FIXME: keep modifier around. */
+             ev->buttons = event.button.button;
+             ev->double_click = 0;
+             ev->triple_click = 0;
+
+             ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
+             break;
+          }
+          case SDL_VIDEORESIZE:
+          {
+             Ecore_Sdl_Event_Video_Resize       *ev;
+
+             ev = malloc(sizeof (Ecore_Sdl_Event_Video_Resize));
+             ev->w = event.resize.w;
+             ev->h = event.resize.h;
+
+             ecore_event_add(ECORE_SDL_EVENT_RESIZE, ev, NULL, NULL);
+             break;
+          }
+          case SDL_VIDEOEXPOSE:
+             ecore_event_add(ECORE_SDL_EVENT_EXPOSE, NULL, NULL, NULL);
+             break;
+          case SDL_QUIT:
+             ecore_main_loop_quit();
+             break;
+
+          case SDL_KEYDOWN:
+          {
+            Ecore_SDL_Pressed *entry;
+             Ecore_Event_Key *ev;
+
+            entry = (Ecore_SDL_Pressed*) eina_rbtree_inline_lookup(repeat, &event.key.keysym.sym, sizeof (event.key.keysym.sym),
+                                                                   EINA_RBTREE_CMP_KEY_CB(_ecore_sdl_pressed_node), NULL);
+            if (entry)
+              {
+                 ev = _ecore_sdl_event_key(&event, time);
+                 if (ev) ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
+              }
+
+            ev = _ecore_sdl_event_key(&event, time);
+            if (ev) ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
+
+            if (!entry)
+              {
+                 entry = malloc(sizeof (Ecore_SDL_Pressed));
+                 if (!entry) break;
+
+                 entry->key = event.key.keysym.sym;
+
+                 repeat = eina_rbtree_inline_insert(repeat, EINA_RBTREE_GET(entry),
+                                                    EINA_RBTREE_CMP_NODE_CB(_ecore_sdl_pressed_key), NULL);
+              }
+             break;
+          }
+          case SDL_KEYUP:
+          {
+             Ecore_Event_Key *ev;
+            Ecore_SDL_Pressed *entry;
+
+            entry = (Ecore_SDL_Pressed*) eina_rbtree_inline_lookup(repeat, &event.key.keysym.sym, sizeof (event.key.keysym.sym),
+                                                                   EINA_RBTREE_CMP_KEY_CB(_ecore_sdl_pressed_node), NULL);
+            if (entry)
+              {
+                 repeat = eina_rbtree_inline_remove(repeat, EINA_RBTREE_GET(entry),
+                                                    EINA_RBTREE_CMP_NODE_CB(_ecore_sdl_pressed_key), NULL);
+                 free(entry);
+              }
+
+            ev = _ecore_sdl_event_key(&event, time);
+            if (ev) ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
+             break;
+          }
+          case SDL_ACTIVEEVENT:
+             /* FIXME: Focus gain. */
+             break;
+          case SDL_SYSWMEVENT:
+          case SDL_USEREVENT:
+          case SDL_JOYAXISMOTION:
+          case SDL_JOYBALLMOTION:
+          case SDL_JOYHATMOTION:
+          case SDL_JOYBUTTONDOWN:
+          case SDL_JOYBUTTONUP:
+          default:
+             break;
+          }
+     }
+}
diff --git a/src/lib/ecore_sdl/ecore_sdl_private.h b/src/lib/ecore_sdl/ecore_sdl_private.h
new file mode 100644 (file)
index 0000000..37e9570
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _ECORE_SDL_PRIVATE_H
+# define _ECORE_SDL_PRIVATE_H
+
+extern int _ecore_sdl_log_dom;
+
+# ifdef ECORE_SDL_DEFAULT_LOG_COLOR
+#  undef ECORE_SDL_DEFAULT_LOG_COLOR 
+# endif
+# define ECORE_SDL_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+  
+# ifdef ERR
+#  undef ERR
+# endif
+# define ERR(...) EINA_LOG_DOM_ERR(_ecore_sdl_log_dom, __VA_ARGS__)
+  
+# ifdef DBG
+#  undef DBG
+# endif
+# define DBG(...) EINA_LOG_DOM_DBG(_ecore_sdl_log_dom, __VA_ARGS__)
+  
+# ifdef INF
+#  undef INF
+# endif
+# define INF(...) EINA_LOG_DOM_INFO(_ecore_sdl_log_dom, __VA_ARGS__)
+  
+# ifdef WRN
+#  undef WRN
+# endif
+# define WRN(...) EINA_LOG_DOM_WARN(_ecore_sdl_log_dom, __VA_ARGS__)
+  
+# ifdef CRIT
+#  undef CRIT
+# endif
+# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_sdl_log_dom, __VA_ARGS__)
+  
+#endif
diff --git a/src/lib/ecore_win32/.cvsignore b/src/lib/ecore_win32/.cvsignore
new file mode 100644 (file)
index 0000000..6607302
--- /dev/null
@@ -0,0 +1,6 @@
+.libs
+.deps
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/lib/ecore_win32/Ecore_Win32.h b/src/lib/ecore_win32/Ecore_Win32.h
new file mode 100644 (file)
index 0000000..6b310d3
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef __ECORE_WIN32_H__
+#define __ECORE_WIN32_H__
+
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_WIN32_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_WIN32_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct _Ecore_Win32_Window Ecore_Win32_Window;
+typedef void Ecore_Win32_Cursor;
+
+/* Window state */
+
+typedef enum
+{
+   /* The window is iconified. */
+   ECORE_WIN32_WINDOW_STATE_ICONIFIED,
+   /* The window is a modal dialog box. */
+   ECORE_WIN32_WINDOW_STATE_MODAL,
+   /* The window manager should keep the window's position fixed
+    * even if the virtual desktop scrolls. */
+   ECORE_WIN32_WINDOW_STATE_STICKY,
+   /* The window has the maximum vertical size. */
+   ECORE_WIN32_WINDOW_STATE_MAXIMIZED_VERT,
+   /* The window has the maximum horizontal size. */
+   ECORE_WIN32_WINDOW_STATE_MAXIMIZED_HORZ,
+   /* The window has the maximum horizontal and vertical size. */
+   ECORE_WIN32_WINDOW_STATE_MAXIMIZED,
+   /* The window is shaded. */
+   ECORE_WIN32_WINDOW_STATE_SHADED,
+   /* The window is invisible (i.e. minimized/iconified) */
+   ECORE_WIN32_WINDOW_STATE_HIDDEN,
+   /* The window should fill the entire screen and have no
+    * window border/decorations */
+   ECORE_WIN32_WINDOW_STATE_FULLSCREEN,
+   /* The following are not documented because they are not
+    * intended for use in applications. */
+   ECORE_WIN32_WINDOW_STATE_ABOVE,
+   ECORE_WIN32_WINDOW_STATE_BELOW,
+   /* FIXME: Documentation */
+   ECORE_WIN32_WINDOW_STATE_DEMANDS_ATTENTION,
+   /* Unknown state */
+   ECORE_WIN32_WINDOW_STATE_UNKNOWN
+} Ecore_Win32_Window_State;
+
+/* Window type */
+
+typedef enum
+{
+   /* Desktop feature*/
+   ECORE_WIN32_WINDOW_TYPE_DESKTOP,
+   /* Dock window (should be on top of other windows */
+   ECORE_WIN32_WINDOW_TYPE_DOCK,
+   /* Toolbar window */
+   ECORE_WIN32_WINDOW_TYPE_TOOLBAR,
+   /* Menu window */
+   ECORE_WIN32_WINDOW_TYPE_MENU,
+   /* Small persistent utility window, such as a palette or toolbox */
+   ECORE_WIN32_WINDOW_TYPE_UTILITY,
+   /* Splash screen window displayed as an application is starting up */
+   ECORE_WIN32_WINDOW_TYPE_SPLASH,
+   /* Dialog window */
+   ECORE_WIN32_WINDOW_TYPE_DIALOG,
+   /* Normal top-level window */
+   ECORE_WIN32_WINDOW_TYPE_NORMAL,
+   /* Unknown type */
+   ECORE_WIN32_WINDOW_TYPE_UNKNOWN
+} Ecore_Win32_Window_Type;
+
+/*cursor shapes */
+
+typedef enum
+{
+   ECORE_WIN32_CURSOR_SHAPE_APP_STARTING, /* Standard arrow and small hourglass */
+   ECORE_WIN32_CURSOR_SHAPE_ARROW,        /* Standard arrow */
+   ECORE_WIN32_CURSOR_SHAPE_CROSS,        /* Crosshair */
+   ECORE_WIN32_CURSOR_SHAPE_HAND,         /* Hand */
+   ECORE_WIN32_CURSOR_SHAPE_HELP,         /* Arrow and question mark */
+   ECORE_WIN32_CURSOR_SHAPE_I_BEAM,       /* I-beam */
+   ECORE_WIN32_CURSOR_SHAPE_NO,           /* Slashed circle */
+   ECORE_WIN32_CURSOR_SHAPE_SIZE_ALL,     /* Four-pointed arrow pointing north, south, east, and west */
+   ECORE_WIN32_CURSOR_SHAPE_SIZE_NESW,    /* Double-pointed arrow pointing northeast and southwest */
+   ECORE_WIN32_CURSOR_SHAPE_SIZE_NS,      /* Double-pointed arrow pointing north and south */
+   ECORE_WIN32_CURSOR_SHAPE_SIZE_NWSE,    /* Double-pointed arrow pointing northwest and southeast */
+   ECORE_WIN32_CURSOR_SHAPE_SIZE_WE,      /* Double-pointed arrow pointing west and east */
+   ECORE_WIN32_CURSOR_SHAPE_UP_ARROW,     /* Vertical arrow */
+   ECORE_WIN32_CURSOR_SHAPE_WAIT          /* Hourglass */
+} Ecore_Win32_Cursor_Shape;
+
+/* Events */
+
+typedef struct _Ecore_Win32_Event_Mouse_In              Ecore_Win32_Event_Mouse_In;
+typedef struct _Ecore_Win32_Event_Mouse_Out             Ecore_Win32_Event_Mouse_Out;
+typedef struct _Ecore_Win32_Event_Window_Focus_In       Ecore_Win32_Event_Window_Focus_In;
+typedef struct _Ecore_Win32_Event_Window_Focus_Out      Ecore_Win32_Event_Window_Focus_Out;
+typedef struct _Ecore_Win32_Event_Window_Damage         Ecore_Win32_Event_Window_Damage;
+typedef struct _Ecore_Win32_Event_Window_Create         Ecore_Win32_Event_Window_Create;
+typedef struct _Ecore_Win32_Event_Window_Destroy        Ecore_Win32_Event_Window_Destroy;
+typedef struct _Ecore_Win32_Event_Window_Hide           Ecore_Win32_Event_Window_Hide;
+typedef struct _Ecore_Win32_Event_Window_Show           Ecore_Win32_Event_Window_Show;
+typedef struct _Ecore_Win32_Event_Window_Configure      Ecore_Win32_Event_Window_Configure;
+typedef struct _Ecore_Win32_Event_Window_Resize         Ecore_Win32_Event_Window_Resize;
+typedef struct _Ecore_Win32_Event_Window_Delete_Request Ecore_Win32_Event_Window_Delete_Request;
+
+struct _Ecore_Win32_Event_Mouse_In
+{
+   Ecore_Win32_Window *window;
+   int                 x;
+   int                 y;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Mouse_Out
+{
+   Ecore_Win32_Window *window;
+   int                 x;
+   int                 y;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Focus_In
+{
+   Ecore_Win32_Window *window;
+   long  long          time;
+};
+
+struct _Ecore_Win32_Event_Window_Focus_Out
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Damage
+{
+   Ecore_Win32_Window *window;
+   int                 x;
+   int                 y;
+   int                 width;
+   int                 height;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Create
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Destroy
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Hide
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Show
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Configure
+{
+   Ecore_Win32_Window *window;
+   Ecore_Win32_Window *abovewin;
+   int                 x;
+   int                 y;
+   int                 width;
+   int                 height;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Resize
+{
+   Ecore_Win32_Window *window;
+   int                 width;
+   int                 height;
+   long                time;
+};
+
+struct _Ecore_Win32_Event_Window_Delete_Request
+{
+   Ecore_Win32_Window *window;
+   long                time;
+};
+
+#define ECORE_WIN32_DND_EVENT_DRAG_ENTER     1
+#define ECORE_WIN32_DND_EVENT_DRAG_OVER      2
+#define ECORE_WIN32_DND_EVENT_DRAG_LEAVE     3
+#define ECORE_WIN32_DND_EVENT_DROP           4
+
+
+typedef int (*Ecore_Win32_Dnd_DropTarget_Callback)(void *window, int event, int pt_x, int pt_y, void *data, int size);
+
+EAPI extern int ECORE_WIN32_EVENT_MOUSE_IN;
+EAPI extern int ECORE_WIN32_EVENT_MOUSE_OUT;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_FOCUS_IN;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_DAMAGE;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_CREATE;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_DESTROY;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_HIDE;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_SHOW;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_CONFIGURE;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_RESIZE;
+EAPI extern int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST;
+
+
+/* Core */
+
+EAPI int    ecore_win32_init();
+EAPI int    ecore_win32_shutdown();
+EAPI int    ecore_win32_screen_depth_get();
+EAPI long   ecore_win32_current_time_get(void);
+EAPI void   ecore_win32_message_loop_begin (void);
+
+/* Window */
+
+EAPI Ecore_Win32_Window *ecore_win32_window_new(Ecore_Win32_Window *parent,
+                                                int                 x,
+                                                int                 y,
+                                                int                 width,
+                                                int                 height);
+EAPI Ecore_Win32_Window *ecore_win32_window_override_new(Ecore_Win32_Window *parent,
+                                                         int                 x,
+                                                         int                 y,
+                                                         int                 width,
+                                                         int                 height);
+
+EAPI void ecore_win32_window_free(Ecore_Win32_Window *window);
+
+EAPI void *ecore_win32_window_hwnd_get(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_move(Ecore_Win32_Window *window,
+                                  int                 x,
+                                  int                 y);
+
+EAPI void ecore_win32_window_resize(Ecore_Win32_Window *window,
+                                    int                 width,
+                                    int                 height);
+
+EAPI void ecore_win32_window_move_resize(Ecore_Win32_Window *window,
+                                         int                 x,
+                                         int                 y,
+                                         int                 width,
+                                         int                 height);
+
+EAPI void ecore_win32_window_geometry_get(Ecore_Win32_Window *window,
+                                          int                *x,
+                                          int                *y,
+                                          int                *width,
+                                          int                *height);
+
+EAPI void ecore_win32_window_size_get(Ecore_Win32_Window *window,
+                                      int                *width,
+                                      int                *height);
+
+EAPI void ecore_win32_window_size_min_set(Ecore_Win32_Window *window,
+                                          unsigned int        min_width,
+                                          unsigned int        min_height);
+
+EAPI void ecore_win32_window_size_min_get(Ecore_Win32_Window *window,
+                                          unsigned int       *min_width,
+                                          unsigned int       *min_height);
+
+EAPI void ecore_win32_window_size_max_set(Ecore_Win32_Window *window,
+                                          unsigned int        max_width,
+                                          unsigned int        max_height);
+
+EAPI void ecore_win32_window_size_max_get(Ecore_Win32_Window *window,
+                                          unsigned int       *max_width,
+                                          unsigned int       *max_height);
+
+EAPI void ecore_win32_window_size_base_set(Ecore_Win32_Window *window,
+                                           unsigned int        base_width,
+                                           unsigned int        base_height);
+
+EAPI void ecore_win32_window_size_base_get(Ecore_Win32_Window *window,
+                                           unsigned int       *base_width,
+                                           unsigned int       *base_height);
+
+EAPI void ecore_win32_window_size_step_set(Ecore_Win32_Window *window,
+                                           unsigned int        step_width,
+                                           unsigned int        step_height);
+
+EAPI void ecore_win32_window_size_step_get(Ecore_Win32_Window *window,
+                                           unsigned int       *step_width,
+                                           unsigned int       *step_height);
+
+EAPI void ecore_win32_window_show(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_hide(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_raise(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_lower(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_title_set(Ecore_Win32_Window *window,
+                                       const char         *title);
+
+EAPI void ecore_win32_window_focus_set(Ecore_Win32_Window *window);
+
+EAPI void ecore_win32_window_iconified_set(Ecore_Win32_Window *window,
+                                           int                 on);
+
+EAPI void ecore_win32_window_borderless_set(Ecore_Win32_Window *window,
+                                            int                 on);
+
+EAPI void ecore_win32_window_fullscreen_set(Ecore_Win32_Window *window,
+                                            int                 on);
+
+EAPI void ecore_win32_window_shape_set(Ecore_Win32_Window *window,
+                                       unsigned short      width,
+                                       unsigned short      height,
+                                       unsigned char      *mask);
+
+EAPI void ecore_win32_window_cursor_set(Ecore_Win32_Window *window,
+                                        Ecore_Win32_Cursor *cursor);
+
+EAPI void ecore_win32_window_state_set(Ecore_Win32_Window       *window,
+                                       Ecore_Win32_Window_State *state,
+                                       unsigned int              num);
+
+EAPI void ecore_win32_window_state_request_send(Ecore_Win32_Window      *window,
+                                                Ecore_Win32_Window_State state,
+                                                unsigned int             set);
+
+EAPI void ecore_win32_window_type_set(Ecore_Win32_Window      *window,
+                                      Ecore_Win32_Window_Type  type);
+
+/* Cursor */
+
+EAPI Ecore_Win32_Cursor *ecore_win32_cursor_new(const void *pixels_and,
+                                                const void *pixels_xor,
+                                                int         width,
+                                                int         height,
+                                                int         hot_x,
+                                                int         hot_y);
+
+EAPI void                ecore_win32_cursor_free(Ecore_Win32_Cursor *cursor);
+
+EAPI Ecore_Win32_Cursor *ecore_win32_cursor_shape_get(Ecore_Win32_Cursor_Shape shape);
+
+EAPI int                 ecore_win32_cursor_size_get(void);
+
+
+
+/* Drag and drop */
+EAPI int ecore_win32_dnd_init();
+EAPI int ecore_win32_dnd_shutdown();
+EAPI int ecore_win32_dnd_begin(const char *data,
+                               int         size);
+EAPI int ecore_win32_dnd_register_drop_target(Ecore_Win32_Window                 *window,
+                                              Ecore_Win32_Dnd_DropTarget_Callback callback);
+EAPI void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __ECORE_WIN32_H__ */
diff --git a/src/lib/ecore_win32/Makefile.am b/src/lib/ecore_win32/Makefile.am
new file mode 100644 (file)
index 0000000..015f302
--- /dev/null
@@ -0,0 +1,49 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_input \
+@EFL_ECORE_WIN32_BUILD@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+
+if BUILD_ECORE_WIN32
+
+lib_LTLIBRARIES = libecore_win32.la
+
+include_HEADERS = \
+Ecore_Win32.h
+
+libecore_win32_la_SOURCES = \
+ecore_win32.c \
+ecore_win32_cursor.c \
+ecore_win32_dnd.c \
+ecore_win32_dnd_enumformatetc.cpp \
+ecore_win32_dnd_data_object.cpp \
+ecore_win32_dnd_drop_source.cpp \
+ecore_win32_dnd_drop_target.cpp \
+ecore_win32_event.c \
+ecore_win32_window.c
+
+libecore_win32_la_LIBADD = \
+@ecore_win32_libs@ \
+@WIN32_LIBS@ \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@
+
+libecore_win32_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_win32_release_info@
+
+endif
+
+EXTRA_DIST = \
+ecore_win32_private.h \
+ecore_win32_dnd_enumformatetc.h \
+ecore_win32_dnd_data_object.h \
+ecore_win32_dnd_drop_source.h \
+ecore_win32_dnd_drop_target.h
diff --git a/src/lib/ecore_win32/ecore_win32.c b/src/lib/ecore_win32/ecore_win32.c
new file mode 100644 (file)
index 0000000..eb70763
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>   /* for printf */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <windowsx.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+
+/* OLE IID for Drag'n Drop */
+
+# define INITGUID
+# include <basetyps.h>
+DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103L, 0, 0);
+DEFINE_OLEGUID(IID_IDataObject,    0x0000010EL, 0, 0);
+DEFINE_OLEGUID(IID_IDropSource,    0x00000121L, 0, 0);
+DEFINE_OLEGUID(IID_IDropTarget,    0x00000122L, 0, 0);
+DEFINE_OLEGUID(IID_IUnknown,       0x00000000L, 0, 0);
+
+
+/***** Global declarations *****/
+
+HINSTANCE           _ecore_win32_instance = NULL;
+double              _ecore_win32_double_click_time = 0.25;
+long                _ecore_win32_event_last_time = 0;
+Ecore_Win32_Window *_ecore_win32_event_last_window = NULL;
+int                 _ecore_win32_log_dom_global = -1;
+
+int ECORE_WIN32_EVENT_MOUSE_IN              = 0;
+int ECORE_WIN32_EVENT_MOUSE_OUT             = 0;
+int ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = 0;
+int ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = 0;
+int ECORE_WIN32_EVENT_WINDOW_DAMAGE         = 0;
+int ECORE_WIN32_EVENT_WINDOW_CREATE         = 0;
+int ECORE_WIN32_EVENT_WINDOW_DESTROY        = 0;
+int ECORE_WIN32_EVENT_WINDOW_SHOW           = 0;
+int ECORE_WIN32_EVENT_WINDOW_HIDE           = 0;
+int ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = 0;
+int ECORE_WIN32_EVENT_WINDOW_RESIZE         = 0;
+int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = 0;
+
+
+/***** Private declarations *****/
+
+static int       _ecore_win32_init_count = 0;
+
+LRESULT CALLBACK _ecore_win32_window_procedure(HWND   window,
+                                               UINT   message,
+                                               WPARAM window_param,
+                                               LPARAM data_param);
+
+static void      _ecore_win32_error_print_cb(const Eina_Log_Domain *d,
+                                             Eina_Log_Level   level,
+                                             const char      *file,
+                                             const char      *fnc,
+                                             int              line,
+                                             const char      *fmt,
+                                             void            *data,
+                                             va_list          args);
+
+
+/***** API *****/
+
+
+int
+ecore_win32_init()
+{
+   WNDCLASS wc;
+
+   if (++_ecore_win32_init_count != 1)
+     return _ecore_win32_init_count;
+
+   if (!eina_init())
+     return --_ecore_win32_init_count;
+
+   eina_log_print_cb_set(_ecore_win32_error_print_cb, NULL);
+   _ecore_win32_log_dom_global = eina_log_domain_register("ecore_win32", ECORE_WIN32_DEFAULT_LOG_COLOR);
+   if (_ecore_win32_log_dom_global < 0)
+     {
+        EINA_LOG_ERR("Ecore_Win32: Could not register log domain");
+        goto shutdown_eina;
+     }
+
+   if (!ecore_event_init())
+     {
+        ERR("Ecore_Win32: Could not init ecore_event");
+        goto unregister_log_domain;
+     }
+
+   _ecore_win32_instance = GetModuleHandle(NULL);
+   if (!_ecore_win32_instance)
+     {
+        ERR("GetModuleHandle() failed");
+        goto shutdown_ecore_event;
+     }
+
+   memset (&wc, 0, sizeof (WNDCLASS));
+   wc.style = CS_HREDRAW | CS_VREDRAW;
+   wc.lpfnWndProc = _ecore_win32_window_procedure;
+   wc.cbClsExtra = 0;
+   wc.cbWndExtra = 0;
+   wc.hInstance = _ecore_win32_instance;
+   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
+   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+   wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
+   wc.lpszMenuName =  NULL;
+   wc.lpszClassName = ECORE_WIN32_WINDOW_CLASS;
+
+   if(!RegisterClass(&wc))
+     {
+        ERR("RegisterClass() failed");
+        goto free_library;
+     }
+
+   if (!ecore_win32_dnd_init())
+     {
+        ERR("ecore_win32_dnd_init() failed");
+        goto unregister_class;
+     }
+
+   if (!ECORE_WIN32_EVENT_MOUSE_IN)
+     {
+        ECORE_WIN32_EVENT_MOUSE_IN              = ecore_event_type_new();
+        ECORE_WIN32_EVENT_MOUSE_OUT             = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_FOCUS_IN       = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT      = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_DAMAGE         = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_CREATE         = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_DESTROY        = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_SHOW           = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_HIDE           = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_CONFIGURE      = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_RESIZE         = ecore_event_type_new();
+        ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
+     }
+
+   return _ecore_win32_init_count;
+
+ unregister_class:
+   UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance);
+ free_library:
+   FreeLibrary(_ecore_win32_instance);
+ shutdown_ecore_event:
+   ecore_event_shutdown();
+ unregister_log_domain:
+   eina_log_domain_unregister(_ecore_win32_log_dom_global);
+ shutdown_eina:
+   eina_shutdown();
+
+   return --_ecore_win32_init_count;
+}
+
+int
+ecore_win32_shutdown()
+{
+   if (--_ecore_win32_init_count != 0)
+     return _ecore_win32_init_count;
+
+   ecore_win32_dnd_shutdown();
+
+   if (!UnregisterClass(ECORE_WIN32_WINDOW_CLASS, _ecore_win32_instance))
+     INF("UnregisterClass() failed");
+
+   if (!FreeLibrary(_ecore_win32_instance))
+     INF("FreeLibrary() failed");
+
+   _ecore_win32_instance = NULL;
+
+   ecore_event_shutdown();
+   eina_log_domain_unregister(_ecore_win32_log_dom_global);
+   _ecore_win32_log_dom_global = -1;
+   eina_shutdown();
+
+   return _ecore_win32_init_count;
+}
+
+int
+ecore_win32_screen_depth_get()
+{
+   HDC dc;
+   int depth;
+
+   INF("getting screen depth");
+
+   dc = GetDC(NULL);
+   if (!dc)
+     {
+        ERR("GetDC() failed");
+        return 0;
+     }
+
+   depth = GetDeviceCaps(dc, BITSPIXEL);
+   if (!ReleaseDC(NULL, dc))
+     {
+        ERR("ReleaseDC() failed (device context not released)");
+     }
+
+   return depth;
+}
+
+/**
+ * Sets the timeout for a double and triple clicks to be flagged.
+ *
+ * This sets the time between clicks before the double_click flag is
+ * set in a button down event. If 3 clicks occur within double this
+ * time, the triple_click flag is also set.
+ *
+ * @param t The time in seconds
+ */
+void
+ecore_win32_double_click_time_set(double t)
+{
+   if (t < 0.0) t = 0.0;
+   _ecore_win32_double_click_time = t;
+}
+
+/**
+ * Retrieves the double and triple click flag timeout.
+ *
+ * See @ref ecore_win32_double_click_time_set for more information.
+ *
+ * @return The timeout for double clicks in seconds.
+ */
+double
+ecore_win32_double_click_time_get(void)
+{
+   return _ecore_win32_double_click_time;
+}
+
+/**
+ * Return the last event time
+ */
+long
+ecore_win32_current_time_get(void)
+{
+   return _ecore_win32_event_last_time;
+}
+
+
+/***** Private functions definitions *****/
+
+
+LRESULT CALLBACK
+_ecore_win32_window_procedure(HWND   window,
+                              UINT   message,
+                              WPARAM window_param,
+                              LPARAM data_param)
+{
+   Ecore_Win32_Callback_Data *data;
+   POINTS                     pt;
+   DWORD                      coord;
+
+   data = (Ecore_Win32_Callback_Data *)malloc(sizeof(Ecore_Win32_Callback_Data));
+   if (!data) return DefWindowProc(window, message, window_param, data_param);
+
+   data->window = window;
+   data->message = message;
+   data->window_param = window_param;
+   data->data_param = data_param;
+   data->time = GetMessageTime();
+   coord = GetMessagePos();
+   pt = MAKEPOINTS(coord);
+   data->x = pt.x;
+   data->y = pt.y;
+
+   switch (data->message)
+     {
+       /* Keyboard input notifications */
+     case WM_KEYDOWN:
+       _ecore_win32_event_handle_key_press(data, 1);
+       return 0;
+     case WM_CHAR:
+       _ecore_win32_event_handle_key_press(data, 0);
+       return 0;
+     case WM_KEYUP:
+       _ecore_win32_event_handle_key_release(data, 1);
+       return 0;
+     case WM_SETFOCUS:
+       _ecore_win32_event_handle_focus_in(data);
+       return 0;
+     case WM_KILLFOCUS:
+       _ecore_win32_event_handle_focus_out(data);
+       return 0;
+       /* Mouse input notifications */
+     case WM_LBUTTONDOWN:
+       _ecore_win32_event_handle_button_press(data, 1);
+       return 0;
+     case WM_MBUTTONDOWN:
+       _ecore_win32_event_handle_button_press(data, 2);
+       return 0;
+     case WM_RBUTTONDOWN:
+       _ecore_win32_event_handle_button_press(data, 3);
+       return 0;
+     case WM_LBUTTONUP:
+       _ecore_win32_event_handle_button_release(data, 1);
+       return 0;
+     case WM_MBUTTONUP:
+       _ecore_win32_event_handle_button_release(data, 2);
+       return 0;
+     case WM_RBUTTONUP:
+       _ecore_win32_event_handle_button_release(data, 3);
+       return 0;
+     case WM_MOUSEMOVE:
+       {
+          RECT                        rect;
+          struct _Ecore_Win32_Window *w = NULL;
+
+          w = (struct _Ecore_Win32_Window *)GetWindowLong(window, GWL_USERDATA);
+
+          if (GetClientRect(window, &rect))
+            {
+               POINT pt;
+
+               INF("mouse in window");
+
+               pt.x = GET_X_LPARAM(data_param);
+               pt.y = GET_Y_LPARAM(data_param);
+               if (!PtInRect(&rect, pt))
+                 {
+                    if (w->pointer_is_in)
+                      {
+                         w->pointer_is_in = 0;
+                         _ecore_win32_event_handle_leave_notify(data);
+                      }
+                 }
+               else
+                 {
+                    if (!w->pointer_is_in)
+                      {
+                         w->pointer_is_in = 1;
+                         _ecore_win32_event_handle_enter_notify(data);
+                      }
+                 }
+            }
+          else
+            {
+               ERR("GetClientRect() failed");
+            }
+          _ecore_win32_event_handle_motion_notify(data);
+
+          return 0;
+       }
+     case WM_MOUSEWHEEL:
+       _ecore_win32_event_handle_button_press(data, 4);
+       return 0;
+       /* Window notifications */
+     case WM_CREATE:
+       _ecore_win32_event_handle_create_notify(data);
+       return 0;
+     case WM_DESTROY:
+       _ecore_win32_event_handle_destroy_notify(data);
+       return 0;
+     case WM_SHOWWINDOW:
+       if ((data->data_param == SW_OTHERUNZOOM) ||
+           (data->data_param == SW_OTHERUNZOOM))
+         return 0;
+
+       if (data->window_param)
+         _ecore_win32_event_handle_map_notify(data);
+       else
+         _ecore_win32_event_handle_unmap_notify(data);
+
+       return 0;
+     case WM_CLOSE:
+       _ecore_win32_event_handle_delete_request(data);
+       return 0;
+     case WM_MOVING:
+       printf (" * ecore message : moving\n");
+       return TRUE;
+     case WM_MOVE:
+       printf (" * ecore message : moved\n");
+       return 0;
+     case WM_SIZING:
+       printf (" * ecore message : sizing\n");
+       _ecore_win32_event_handle_resize(data);
+       _ecore_win32_event_handle_configure_notify(data);
+       return TRUE;
+     case WM_SIZE:
+       printf (" * ecore message : sized\n");
+       return 0;
+/*      case WM_WINDOWPOSCHANGING: */
+/*        { */
+/*          RECT rect; */
+/*          GetClientRect(window, &rect); */
+/*          printf (" *** ecore message : WINDOWPOSCHANGING %ld %ld\n", */
+/*                  rect.right - rect.left, rect.bottom - rect.top); */
+/*        } */
+/*        _ecore_win32_event_handle_configure_notify(data); */
+/*        return 0; */
+     case WM_WINDOWPOSCHANGED:
+       _ecore_win32_event_handle_configure_notify(data);
+       return 0;
+     case WM_ENTERSIZEMOVE :
+       printf (" * ecore message : WM_ENTERSIZEMOVE \n");
+       return 0;
+     case WM_EXITSIZEMOVE:
+       printf (" * ecore message : WM_EXITSIZEMOVE\n");
+       return 0;
+       /* GDI notifications */
+     case WM_PAINT:
+       {
+         RECT rect;
+
+         if (GetUpdateRect(window, &rect, FALSE))
+           {
+              PAINTSTRUCT ps;
+              HDC         hdc;
+
+              hdc = BeginPaint(window, &ps);
+              data->update = rect;
+              _ecore_win32_event_handle_expose(data);
+              EndPaint(window, &ps);
+           }
+         return 0;
+       }
+     case WM_SETREDRAW:
+       printf (" * ecore message : WM_SETREDRAW\n");
+       return 0;
+     case WM_SYNCPAINT:
+       printf (" * ecore message : WM_SYNCPAINT\n");
+       return 0;
+     default:
+       return DefWindowProc(window, message, window_param, data_param);
+     }
+}
+
+static void
+_ecore_win32_error_print_cb(const Eina_Log_Domain *d __UNUSED__,
+                            Eina_Log_Level   level __UNUSED__,
+                            const char     *file __UNUSED__,
+                            const char     *fnc,
+                            int             line,
+                            const char     *fmt,
+                            void           *data __UNUSED__,
+                            va_list         args)
+{
+   fprintf(stderr, "[%s:%d] ", fnc, line);
+   vfprintf(stderr, fmt, args);
+}
diff --git a/src/lib/ecore_win32/ecore_win32_cursor.c b/src/lib/ecore_win32/ecore_win32_cursor.c
new file mode 100644 (file)
index 0000000..5979e76
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Eina.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+
+/***** API *****/
+
+Ecore_Win32_Cursor *
+ecore_win32_cursor_new(const void *pixels_and,
+                       const void *pixels_xor,
+                       int         width,
+                       int         height,
+                       int         hot_x,
+                       int         hot_y)
+{
+   Ecore_Win32_Cursor *cursor = NULL;
+   int                 cursor_width;
+   int                 cursor_height;
+
+   INF("creating cursor");
+
+   cursor_width = GetSystemMetrics(SM_CXCURSOR);
+   cursor_height = GetSystemMetrics(SM_CYCURSOR);
+
+   if ((cursor_width != width) ||
+       (cursor_height != height))
+     return NULL;
+
+   if (!(cursor = CreateCursor(_ecore_win32_instance,
+                               hot_x, hot_y,
+                               width, height,
+                               pixels_and,
+                               pixels_xor)))
+     return NULL;
+
+   return cursor;
+}
+
+void
+ecore_win32_cursor_free(Ecore_Win32_Cursor *cursor)
+{
+   INF("destroying cursor");
+
+   DestroyCursor(cursor);
+}
+
+Ecore_Win32_Cursor *
+ecore_win32_cursor_shape_get(Ecore_Win32_Cursor_Shape shape)
+{
+   Ecore_Win32_Cursor *cursor = NULL;
+   const char         *cursor_name;
+
+   INF("geting shape cursor");
+
+   switch (shape)
+     {
+       case ECORE_WIN32_CURSOR_SHAPE_APP_STARTING:
+         cursor_name = IDC_APPSTARTING;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_ARROW:
+         cursor_name = IDC_ARROW;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_CROSS:
+         cursor_name = IDC_CROSS;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_HAND:
+         cursor_name = IDC_HAND;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_HELP:
+         cursor_name = IDC_HELP;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_I_BEAM:
+         cursor_name = IDC_IBEAM;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_NO:
+         cursor_name = IDC_NO;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_SIZE_ALL:
+         cursor_name = IDC_SIZEALL;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_SIZE_NESW:
+         cursor_name = IDC_SIZENESW;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_SIZE_NS:
+         cursor_name = IDC_SIZENS;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_SIZE_NWSE:
+         cursor_name = IDC_SIZENWSE;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_SIZE_WE:
+         cursor_name = IDC_SIZEWE;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_UP_ARROW:
+         cursor_name = IDC_UPARROW;
+         break;
+       case ECORE_WIN32_CURSOR_SHAPE_WAIT:
+         cursor_name = IDC_WAIT;
+         break;
+     default:
+         return NULL;
+     }
+
+   if (!(cursor = LoadCursor(NULL, cursor_name)))
+     return NULL;
+
+   return cursor;
+}
+
+int
+ecore_win32_cursor_size_get(void)
+{
+   int width;
+   int height;
+
+   INF("geting size cursor");
+
+   width = GetSystemMetrics(SM_CXCURSOR);
+   height = GetSystemMetrics(SM_CYCURSOR);
+   return (width > height) ? width : height;
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd.c b/src/lib/ecore_win32/ecore_win32_dnd.c
new file mode 100755 (executable)
index 0000000..25363b2
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <windows.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+
+static int _ecore_win32_dnd_init_count = 0;
+
+static HANDLE DataToHandle(const char *data, int size)
+{
+   char *ptr;
+   ptr = (char *)GlobalAlloc(GMEM_FIXED, size);
+   memcpy(ptr, data, size);
+   return ptr;
+}
+
+
+int
+ecore_win32_dnd_init()
+{
+   if (_ecore_win32_dnd_init_count > 0)
+     {
+       _ecore_win32_dnd_init_count++;
+       return _ecore_win32_dnd_init_count;
+     }
+
+   if (OleInitialize(NULL) != S_OK)
+     return 0;
+
+   _ecore_win32_dnd_init_count++;
+
+   return _ecore_win32_dnd_init_count;
+}
+
+int ecore_win32_dnd_shutdown()
+{
+   _ecore_win32_dnd_init_count--;
+   if (_ecore_win32_dnd_init_count > 0) return _ecore_win32_dnd_init_count;
+
+   OleUninitialize();
+
+   if (_ecore_win32_dnd_init_count < 0) _ecore_win32_dnd_init_count = 0;
+
+   return _ecore_win32_dnd_init_count;
+}
+
+int ecore_win32_dnd_begin(const char *data,
+                          int         size)
+{
+   IDataObject *pDataObject = NULL;
+   IDropSource *pDropSource = NULL;
+   FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+   STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
+   int res = 0;
+
+   if (data == NULL)
+      return 0;
+   if (size < 0)
+      size = strlen(data) + 1;
+
+   stgmed.hGlobal = DataToHandle(data, size);
+
+   // create the data object
+   pDataObject = (IDataObject *)_ecore_win32_dnd_data_object_new((void *)&fmtetc,
+                                                                 (void *)&stgmed,
+                                                                 1);
+   pDropSource = (IDropSource *)_ecore_win32_dnd_drop_source_new();
+
+   if (pDataObject && pDropSource)
+   {
+      DWORD dwResult;
+      DWORD dwEffect = DROPEFFECT_COPY;
+
+      // do the drag-drop!
+      dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY, &dwEffect);
+
+      // finished. Check the return values to see if we need to do anything else
+      if (dwResult == DRAGDROP_S_DROP)
+      {
+         //printf(">>> \"%s\" Dropped <<<\n", str);
+         if(dwEffect == DROPEFFECT_MOVE)
+         {
+            // remove the data we just dropped from active document
+         }
+      }
+      //else if (dwResult == DRAGDROP_S_CANCEL)
+      //   printf("DND cancelled\n");
+      //else
+      //   printf("DND error\n");
+
+      res = 1;
+   }
+
+   _ecore_win32_dnd_data_object_free(pDataObject);
+   _ecore_win32_dnd_drop_source_free(pDropSource);
+
+   // cleanup
+   ReleaseStgMedium(&stgmed);
+   return (int)res;
+}
+
+int ecore_win32_dnd_register_drop_target(Ecore_Win32_Window                 *window,
+                                         Ecore_Win32_Dnd_DropTarget_Callback callback)
+{
+   struct _Ecore_Win32_Window *wnd = (struct _Ecore_Win32_Window *)window;
+
+   if (window == NULL)
+      return 0;
+
+   wnd->dnd_drop_target = _ecore_win32_dnd_register_drop_window(wnd->window,
+                                                                callback,
+                                                                (void *)wnd);
+   return (int)(wnd->dnd_drop_target != NULL);
+}
+
+void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window)
+{
+   struct _Ecore_Win32_Window *wnd = (struct _Ecore_Win32_Window *)window;
+
+   if (window == NULL)
+      return;
+
+   if (wnd->dnd_drop_target != NULL)
+      _ecore_win32_dnd_unregister_drop_window(wnd->window, wnd->dnd_drop_target);
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp b/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp
new file mode 100644 (file)
index 0000000..6de1035
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <ole2.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+#include "ecore_win32_dnd_enumformatetc.h"
+#include "ecore_win32_dnd_data_object.h"
+
+
+static HGLOBAL DupGlobalMem(HGLOBAL hMem)
+{
+   DWORD len = (DWORD)GlobalSize(hMem);
+   PVOID source = GlobalLock(hMem);
+   PVOID dest = GlobalAlloc(GMEM_FIXED, len);
+   memcpy(dest, source, len);
+   GlobalUnlock(hMem);
+   return dest;
+}
+
+// structors
+
+DataObject::DataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
+{
+   assert(fmtetc != NULL);
+   assert(stgmed != NULL);
+   assert(count > 0);
+
+   // reference count must ALWAYS start at 1
+   ref_count_ = 1;
+   formats_num_ = count;
+
+   format_etc_ = new FORMATETC[count];
+   stg_medium_ = new STGMEDIUM[count];
+
+   for(int i = 0; i < count; i++)
+   {
+      format_etc_[i] = fmtetc[i];
+      stg_medium_[i] = stgmed[i];
+   }
+}
+
+DataObject::~DataObject()
+{
+   delete[] format_etc_;
+   delete[] stg_medium_;
+}
+
+
+// IUnknown
+
+HRESULT DataObject::QueryInterface(REFIID iid, void **ppvObject)
+{
+   // check to see what interface has been requested
+   if ((iid == IID_IDataObject) || (iid == IID_IUnknown))
+   {
+      AddRef();
+      *ppvObject = this;
+      return S_OK;
+   }
+   *ppvObject = 0;
+   return E_NOINTERFACE;
+}
+
+ULONG DataObject::AddRef()
+{
+   return InterlockedIncrement(&ref_count_);
+}
+
+ULONG DataObject::Release()
+{
+   LONG count = InterlockedDecrement(&ref_count_);
+   if(count == 0)
+   {
+      delete this;
+      return 0;
+   }
+   return count;
+}
+
+// IDataObject
+
+HRESULT DataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
+{
+   assert(pMedium != NULL);
+   int idx;
+
+   // try to match the specified FORMATETC with one of our supported formats
+   if((idx = lookup_format_etc(pFormatEtc)) == -1)
+      return DV_E_FORMATETC;
+
+   // found a match - transfer data into supplied storage medium
+   pMedium->tymed = format_etc_[idx].tymed;
+   pMedium->pUnkForRelease = 0;
+
+   // copy the data into the caller's storage medium
+   switch(format_etc_[idx].tymed)
+   {
+   case TYMED_HGLOBAL:
+      pMedium->hGlobal = DupGlobalMem(stg_medium_[idx].hGlobal);
+      break;
+
+   default:
+      return DV_E_FORMATETC;
+   }
+
+   return S_OK;
+}
+
+HRESULT DataObject::GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pmedium)
+{
+   return DATA_E_FORMATETC;
+}
+
+HRESULT DataObject::QueryGetData(FORMATETC *pFormatEtc)
+{
+   return (lookup_format_etc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
+}
+
+HRESULT DataObject::GetCanonicalFormatEtc(FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut)
+{
+   // Apparently we have to set this field to NULL even though we don't do anything else
+   pFormatEtcOut->ptd = NULL;
+   return E_NOTIMPL;
+}
+
+HRESULT DataObject::SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease)
+{
+   return E_NOTIMPL;
+}
+
+HRESULT DataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
+{
+   // only the get direction is supported for OLE
+   if(dwDirection == DATADIR_GET)
+   {
+      // for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
+      // to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
+      return CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
+   }
+   else
+   {
+      // the direction specified is not supported for drag+drop
+      return E_NOTIMPL;
+   }
+}
+
+HRESULT DataObject::DAdvise(FORMATETC *pFormatEtc,  DWORD advf, IAdviseSink *, DWORD *)
+{
+   return OLE_E_ADVISENOTSUPPORTED;
+}
+
+HRESULT DataObject::DUnadvise(DWORD dwConnection)
+{
+   return OLE_E_ADVISENOTSUPPORTED;
+}
+
+HRESULT DataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise)
+{
+   return OLE_E_ADVISENOTSUPPORTED;
+}
+
+// internal helper function
+
+int DataObject::lookup_format_etc(FORMATETC *pFormatEtc)
+{
+   // check each of our formats in turn to see if one matches
+   for(int i = 0; i < formats_num_; i++)
+   {
+      if((format_etc_[i].tymed & pFormatEtc->tymed) &&
+         (format_etc_[i].cfFormat == pFormatEtc->cfFormat) &&
+         (format_etc_[i].dwAspect == pFormatEtc->dwAspect))
+      {
+         // return index of stored format
+         return i;
+      }
+   }
+
+   // error, format not found
+   return -1;
+}
+
+void *_ecore_win32_dnd_data_object_new(void *fmtetc, void *stgmeds, int count)
+{
+   IDataObject *object = new DataObject((FORMATETC *)fmtetc, (STGMEDIUM *)stgmeds, (UINT)count);
+   assert(object != NULL);
+   return object;
+}
+
+void _ecore_win32_dnd_data_object_free(void *data_object)
+{
+   if (!data_object)
+     return;
+
+   IDataObject *object = (IDataObject *)data_object;
+   object->Release();
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_data_object.h b/src/lib/ecore_win32/ecore_win32_dnd_data_object.h
new file mode 100644 (file)
index 0000000..3d289cf
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __ECORE_WIN32_DND_DATA_OBJECT_H__
+#define __ECORE_WIN32_DND_DATA_OBJECT_H__
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <objbase.h>
+
+
+class DataObject : public IDataObject
+{
+ private:
+
+   LONG       ref_count_;
+   int        formats_num_;
+   FORMATETC *format_etc_;
+   STGMEDIUM *stg_medium_;
+
+ private: // internal helper function
+
+   int lookup_format_etc(FORMATETC *format_etc);
+
+ public: // structors
+
+   DataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count);
+   ~DataObject();
+
+ public: // IUnknown
+
+   HRESULT __stdcall QueryInterface(REFIID iid, void **ppvObject);
+   ULONG   __stdcall AddRef();
+   ULONG   __stdcall Release();
+
+ public: // IDataObject
+
+   HRESULT __stdcall GetData(FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
+   HRESULT __stdcall GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pmedium);
+   HRESULT __stdcall QueryGetData(FORMATETC *pFormatEtc);
+   HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut);
+   HRESULT __stdcall SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease);
+   HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
+   HRESULT __stdcall DAdvise(FORMATETC *pFormatEtc,  DWORD advf, IAdviseSink *, DWORD *);
+   HRESULT __stdcall DUnadvise(DWORD dwConnection);
+   HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppEnumAdvise);
+};
+
+
+#endif /* __ECORE_WIN32_DND_DATA_OBJECT_H__ */
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp b/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp
new file mode 100644 (file)
index 0000000..065ac6a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+
+#include "ecore_win32_dnd_drop_source.h"
+
+#include "ecore_win32_private.h"
+
+// structors
+
+// reference count must ALWAYS start at 1
+DropSource::DropSource() : ref_count_(1)
+{ }
+
+
+// IUnknown
+
+HRESULT DropSource::QueryInterface(REFIID iid, void **ppvObject)
+{
+   // check to see what interface has been requested
+   if (iid == IID_IDropSource || iid == IID_IUnknown)
+   {
+      AddRef();
+      *ppvObject = this;
+      return S_OK;
+   }
+   *ppvObject = 0;
+   return E_NOINTERFACE;
+}
+
+ULONG DropSource::AddRef()
+{
+   return InterlockedIncrement(&ref_count_);
+}
+
+ULONG DropSource::Release()
+{
+   LONG count = InterlockedDecrement(&ref_count_);
+   if(count == 0)
+   {
+      delete this;
+      return 0;
+   }
+   return count;
+}
+
+
+// IDropSource
+
+HRESULT DropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
+{
+    // if the Escape key has been pressed since the last call, cancel the drop
+    if(fEscapePressed == TRUE)
+        return DRAGDROP_S_CANCEL;
+
+    // if the LeftMouse button has been released, then do the drop!
+    if((grfKeyState & MK_LBUTTON) == 0)
+        return DRAGDROP_S_DROP;
+
+    // continue with the drag-drop
+    return S_OK;
+}
+
+HRESULT DropSource::GiveFeedback(DWORD dwEffect)
+{
+    return DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+
+// ecore_win32 private functions
+
+void *_ecore_win32_dnd_drop_source_new()
+{
+   IDropSource *object = new DropSource();
+   assert(object != NULL);
+   return object;
+}
+
+void _ecore_win32_dnd_drop_source_free(void *drop_source)
+{
+   if (!drop_source)
+     return;
+
+   IDropSource *object = (IDropSource *)drop_source;
+   object->Release();
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h b/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h
new file mode 100644 (file)
index 0000000..9081f46
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __ECORE_WIN32_DND_DROP_SOURCE_H__
+#define __ECORE_WIN32_DND_DROP_SOURCE_H__
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <ole2.h>
+
+#include "Ecore_Win32.h"
+
+
+class DropSource : public IDropSource
+{
+ private:
+
+   LONG ref_count_;
+
+ public: // structors
+
+   DropSource();
+
+ public: // IUnknown
+
+   HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);
+   ULONG   __stdcall AddRef();
+   ULONG   __stdcall Release();
+
+ public: // IDropSource
+
+   HRESULT __stdcall QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
+   HRESULT __stdcall GiveFeedback(DWORD dwEffect);
+};
+
+
+#endif /* __ECORE_WIN32_DND_DROP_SOURCE_H__ */
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp b/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp
new file mode 100644 (file)
index 0000000..5051316
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_win32_dnd_drop_target.h"
+
+#include "ecore_win32_private.h"
+
+
+// structors
+
+DropTarget::DropTarget(HWND window, Ecore_Win32_Dnd_DropTarget_Callback callback, void *window_obj_ptr)
+  : ref_count_(1)
+  , window_(window)
+  , allow_drop_(false)
+  , drop_callback_(callback)
+  ,drop_callback_ptr_(window_obj_ptr)
+{ }
+
+
+// IUnknown
+
+HRESULT DropTarget::QueryInterface(REFIID iid, void **ppvObject)
+{
+   // check to see what interface has been requested
+   if (iid == IID_IDropTarget || iid == IID_IUnknown)
+   {
+      AddRef();
+      *ppvObject = this;
+      return S_OK;
+   }
+   *ppvObject = 0;
+
+   return E_NOINTERFACE;
+}
+
+ULONG DropTarget::AddRef()
+{
+   return InterlockedIncrement(&ref_count_);
+}
+
+ULONG DropTarget::Release()
+{
+   LONG count = InterlockedDecrement(&ref_count_);
+   if (count == 0)
+   {
+      delete this;
+      return 0;
+   }
+
+   return count;
+}
+
+
+// IDropTarget
+
+HRESULT DropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
+{
+   // does the dataobject contain data we want?
+   allow_drop_ = QueryDataObject(pDataObject) &&
+      (drop_callback_ == NULL ||
+      (drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_ENTER, pt.x, pt.y, NULL, 0) != 0));
+
+   if (allow_drop_)
+   {
+      // get the dropeffect based on keyboard state
+      *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
+      SetFocus(window_);
+      //PositionCursor(_hwnd, pt);
+   }
+   else
+      *pdwEffect = DROPEFFECT_NONE;
+   return S_OK;
+}
+
+HRESULT DropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+{
+   allow_drop_ =
+     (drop_callback_ == NULL) ||
+     (drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_OVER, pt.x, pt.y, NULL, 0) != 0);
+
+   if (allow_drop_)
+   {
+      *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
+      //PositionCursor(m_hWnd, pt);
+   }
+   else
+   {
+      *pdwEffect = DROPEFFECT_NONE;
+   }
+
+   return S_OK;
+}
+
+HRESULT DropTarget::DragLeave()
+{
+   POINT pt;
+
+   GetCursorPos(&pt);
+   if (drop_callback_ != NULL)
+     drop_callback_(drop_callback_ptr_, ECORE_WIN32_DND_EVENT_DRAG_LEAVE, pt.x, pt.y, NULL, 0);
+
+   return S_OK;
+}
+
+HRESULT DropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
+{
+   if (allow_drop_)
+   {
+      // construct a FORMATETC object
+      FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+      STGMEDIUM stgmed;
+
+      // See if the dataobject contains any TEXT stored as a HGLOBAL
+      if (pDataObject->QueryGetData(&fmtetc) == S_OK)
+      {
+         // Yippie! the data is there, so go get it!
+         if (pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
+         {
+            // we asked for the data as a HGLOBAL, so access it appropriately
+            PVOID data = GlobalLock(stgmed.hGlobal);
+            UINT size = GlobalSize(stgmed.hGlobal);
+
+            if (drop_callback_ != NULL)
+            {
+               drop_callback_(drop_callback_ptr_,
+                              ECORE_WIN32_DND_EVENT_DROP,
+                              pt.x, pt.y,
+                              data, size);
+            }
+
+            GlobalUnlock(stgmed.hGlobal);
+
+            // release the data using the COM API
+            ReleaseStgMedium(&stgmed);
+         }
+      }
+      *pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
+   }
+   else
+   {
+      *pdwEffect = DROPEFFECT_NONE;
+   }
+
+   return S_OK;
+}
+
+
+// internal helper function
+
+DWORD DropTarget::DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed)
+{
+   DWORD dwEffect = 0;
+
+   // 1. check "pt" -> do we allow a drop at the specified coordinates?
+
+   // 2. work out that the drop-effect should be based on grfKeyState
+   if (grfKeyState & MK_CONTROL)
+   {
+          dwEffect = dwAllowed & DROPEFFECT_COPY;
+   }
+   else if (grfKeyState & MK_SHIFT)
+   {
+          dwEffect = dwAllowed & DROPEFFECT_MOVE;
+   }
+
+   // 3. no key-modifiers were specified (or drop effect not allowed), so
+   //    base the effect on those allowed by the dropsource
+   if (dwEffect == 0)
+   {
+          if (dwAllowed & DROPEFFECT_COPY) dwEffect = DROPEFFECT_COPY;
+          if (dwAllowed & DROPEFFECT_MOVE) dwEffect = DROPEFFECT_MOVE;
+   }
+
+   return dwEffect;
+}
+
+bool DropTarget::QueryDataObject(IDataObject *pDataObject)
+{
+    FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+
+    // does the data object support CF_TEXT using a HGLOBAL?
+    return pDataObject->QueryGetData(&fmtetc) == S_OK;
+}
+
+
+// ecore_win32 private functions
+
+void *_ecore_win32_dnd_register_drop_window(HWND hwnd,  Ecore_Win32_Dnd_DropTarget_Callback callback, void *ptr)
+{
+   DropTarget *pDropTarget = new DropTarget(hwnd, callback, ptr);
+
+   if (pDropTarget == NULL)
+     return NULL;
+
+   // acquire a strong lock
+   if (FAILED(CoLockObjectExternal(pDropTarget, TRUE, FALSE)))
+     {
+        delete pDropTarget;
+        return NULL;
+     }
+
+   // tell OLE that the window is a drop target
+   if (FAILED(RegisterDragDrop(hwnd, pDropTarget)))
+     {
+        delete pDropTarget;
+        return NULL;
+     }
+
+   return pDropTarget;
+}
+
+void _ecore_win32_dnd_unregister_drop_window(HWND hwnd, void *drop_target)
+{
+   IDropTarget *pDropTarget = (IDropTarget *)drop_target;
+
+   if (drop_target == NULL)
+     return;
+
+   // remove drag+drop
+   RevokeDragDrop(hwnd);
+
+   // remove the strong lock
+   CoLockObjectExternal(pDropTarget, FALSE, TRUE);
+
+   // release our own reference
+   pDropTarget->Release();
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h b/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h
new file mode 100644 (file)
index 0000000..24c3de3
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __ECORE_WIN32_DND_DROP_TARGET_H__
+#define __ECORE_WIN32_DND_DROP_TARGET_H__
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <ole2.h>
+
+#include "Ecore_Win32.h"
+
+
+class DropTarget : public IDropTarget
+{
+ private:
+
+   LONG                                ref_count_;
+   HWND                                window_;
+   bool                                allow_drop_;
+   Ecore_Win32_Dnd_DropTarget_Callback drop_callback_;
+   void                               *drop_callback_ptr_;
+
+ private: // internal helper function
+
+   DWORD DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed);
+   bool  QueryDataObject(IDataObject *pDataObject);
+
+ public: // structors
+
+   DropTarget(HWND hwnd, Ecore_Win32_Dnd_DropTarget_Callback callback, void *window_obj_ptr);
+
+public: // IUnknown
+
+   HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject);
+   ULONG   __stdcall AddRef();
+   ULONG   __stdcall Release();
+
+ public: // IDropTarget
+
+   HRESULT __stdcall DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+   HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+   HRESULT __stdcall DragLeave();
+   HRESULT __stdcall Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+};
+
+
+#endif /* __ECORE_WIN32_DND_DROP_TARGET_H__ */
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp b/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp
new file mode 100644 (file)
index 0000000..a3858bc
--- /dev/null
@@ -0,0 +1,157 @@
+
+#include <ole2.h>
+
+#include "ecore_win32_dnd_enumformatetc.h"
+
+
+// structors
+
+CEnumFormatEtc::CEnumFormatEtc(FORMATETC *format_etc, int formats_num)
+  : ref_count_(1)
+  , index_(0)
+  , formats_num_(formats_num)
+  , format_etc_(new FORMATETC[formats_num])
+{
+   // make a new copy of each FORMATETC structure
+   for (unsigned int i = 0; i < formats_num_; i++)
+     {
+        DeepCopyFormatEtc(&format_etc_[i], &format_etc[i]);
+     }
+}
+
+CEnumFormatEtc::~CEnumFormatEtc()
+{
+   if (format_etc_)
+     {
+        // first free any DVTARGETDEVICE structures
+        for (ULONG i = 0; i < formats_num_; i++)
+          {
+             if (format_etc_[i].ptd)
+               CoTaskMemFree(format_etc_[i].ptd);
+          }
+
+        // now free the main array
+        delete[] format_etc_;
+     }
+}
+
+// IUnknown
+
+ULONG __stdcall CEnumFormatEtc::AddRef(void)
+{
+   // increment object reference count
+   return InterlockedIncrement(&ref_count_);
+}
+
+ULONG __stdcall CEnumFormatEtc::Release(void)
+{
+   // decrement object reference count
+   LONG count = InterlockedDecrement(&ref_count_);
+
+   if (count == 0)
+     {
+        delete this;
+        return 0;
+     }
+   else
+     {
+        return count;
+     }
+}
+
+HRESULT __stdcall CEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject)
+{
+   // check to see what interface has been requested
+   if ((iid == IID_IEnumFORMATETC) || (iid == IID_IUnknown))
+     {
+        AddRef();
+        *ppvObject = this;
+        return S_OK;
+     }
+   else
+     {
+        *ppvObject = 0;
+        return E_NOINTERFACE;
+     }
+}
+
+// IEnumFormatEtc
+
+HRESULT CEnumFormatEtc::Reset(void)
+{
+   index_ = 0;
+   return S_OK;
+}
+
+HRESULT CEnumFormatEtc::Skip(ULONG celt)
+{
+   index_ += celt;
+   return (index_ <= formats_num_) ? S_OK : S_FALSE;
+}
+
+HRESULT CEnumFormatEtc::Clone(IEnumFORMATETC **ppEnumFormatEtc)
+{
+   HRESULT hResult;
+
+   // make a duplicate enumerator
+   hResult = CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
+
+   if (hResult == S_OK)
+     {
+        // manually set the index state
+        ((CEnumFormatEtc *)*ppEnumFormatEtc)->index_ = index_;
+     }
+
+   return hResult;
+}
+
+HRESULT CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
+{
+   ULONG copied = 0;
+
+   // validate arguments
+   if ((celt == 0) || (pFormatEtc == 0))
+     return E_INVALIDARG;
+
+   // copy the FORMATETC structures into the caller's buffer
+   while (index_ < formats_num_ && copied < celt)
+     {
+        DeepCopyFormatEtc(&pFormatEtc[copied], &format_etc_[index_]);
+        copied++;
+        index_++;
+     }
+
+   // store result
+   if (pceltFetched != 0)
+     *pceltFetched = copied;
+
+   // did we copy all that was requested?
+   return (copied == celt) ? S_OK : S_FALSE;
+}
+
+// external functions
+
+void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
+{
+   // copy the source FORMATETC into dest
+   *dest = *source;
+
+   if (source->ptd)
+     {
+        // allocate memory for the DVTARGETDEVICE if necessary
+        dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
+
+        // copy the contents of the source DVTARGETDEVICE into dest->ptd
+        *(dest->ptd) = *(source->ptd);
+     }
+}
+
+HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
+{
+  if((cfmt == 0) || (afmt == 0) || (ppEnumFormatEtc == 0))
+     return E_INVALIDARG;
+
+   *ppEnumFormatEtc = new CEnumFormatEtc(afmt, cfmt);
+
+   return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
+}
diff --git a/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h b/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h
new file mode 100644 (file)
index 0000000..9f17f56
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __ECORE_WIN32_DND_ENUMFORMATETC_H__
+#define __ECORE_WIN32_DND_ENUMFORMATETC_H__
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <objbase.h>
+
+
+class CEnumFormatEtc : public IEnumFORMATETC
+{
+ private:
+
+   LONG       ref_count_;        // Reference count for this COM interface
+   ULONG      index_;           // current enumerator index
+   ULONG      formats_num_;      // number of FORMATETC members
+   FORMATETC *format_etc_;       // array of FORMATETC objects
+
+ public: // structors
+
+   CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats);
+
+   ~CEnumFormatEtc();
+
+ public: // IUnknown
+
+   HRESULT __stdcall  QueryInterface (REFIID iid, void ** ppvObject);
+
+   ULONG   __stdcall  AddRef (void);
+
+   ULONG   __stdcall  Release (void);
+
+ public: // IEnumFormatEtc
+
+   HRESULT __stdcall  Next  (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched);
+
+   HRESULT __stdcall  Skip  (ULONG celt);
+
+   HRESULT __stdcall  Reset (void);
+
+   HRESULT __stdcall  Clone (IEnumFORMATETC ** ppEnumFormatEtc);
+};
+
+void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source);
+
+HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc);
+
+
+#endif /* __ECORE_WIN32_DND_ENUMFORMATETC_H__ */
diff --git a/src/lib/ecore_win32/ecore_win32_event.c b/src/lib/ecore_win32/ecore_win32_event.c
new file mode 100644 (file)
index 0000000..3d57095
--- /dev/null
@@ -0,0 +1,1014 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>   /* for printf */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <windowsx.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+
+/***** Private declarations *****/
+
+
+static Ecore_Win32_Window *_ecore_win32_mouse_down_last_window = NULL;
+static Ecore_Win32_Window *_ecore_win32_mouse_down_last_last_window = NULL;
+static long                _ecore_win32_mouse_down_last_time = 0  ;
+static long                _ecore_win32_mouse_down_last_last_time = 0  ;
+static int                 _ecore_win32_mouse_down_did_triple = 0;
+static int                 _ecore_win32_mouse_up_count = 0;
+
+static void _ecore_win32_event_free_key_down(void *data,
+                                             void *ev);
+
+static void _ecore_win32_event_free_key_up(void *data,
+                                           void *ev);
+
+static int  _ecore_win32_event_keystroke_get(int    key,
+                                             int    is_extended,
+                                             char **keyname,
+                                             char **keysymbol,
+                                             char **keycompose);
+
+static int  _ecore_win32_event_char_get(int    key,
+                                        char **keyname,
+                                        char **keysymbol,
+                                        char **keycompose);
+
+
+/***** Global functions definitions *****/
+
+void
+_ecore_win32_event_handle_key_press(Ecore_Win32_Callback_Data *msg,
+                                    int                        is_keystroke)
+{
+   Ecore_Event_Key *e;
+
+   INF("key pressed");
+
+   e = (Ecore_Event_Key *)malloc(sizeof(Ecore_Event_Key));
+   if (!e) return;
+
+   if (is_keystroke)
+     {
+        if (!_ecore_win32_event_keystroke_get(LOWORD(msg->window_param),
+                                              msg->data_param & 0x01000000,
+                                              (char **)&e->keyname,
+                                              (char **)&e->key,
+                                              (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+        goto store_key;
+     }
+   else
+     {
+        if (!_ecore_win32_event_char_get(LOWORD(msg->window_param),
+                                         (char **)&e->keyname,
+                                         (char **)&e->key,
+                                         (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+
+ store_key:
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+   e->timestamp = msg->time;
+
+   _ecore_win32_event_last_time = e->timestamp;
+
+   ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_win32_event_free_key_down, NULL);
+}
+
+void
+_ecore_win32_event_handle_key_release(Ecore_Win32_Callback_Data *msg,
+                                      int                        is_keystroke)
+{
+   Ecore_Event_Key *e;
+
+   INF("key released");
+
+   e = (Ecore_Event_Key *)calloc(1, sizeof(Ecore_Event_Key));
+   if (!e) return;
+
+   if (is_keystroke)
+     {
+        if (!_ecore_win32_event_keystroke_get(LOWORD(msg->window_param),
+                                              msg->data_param & 0x01000000,
+                                              (char **)&e->keyname,
+                                              (char **)&e->key,
+                                              (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+        goto store_key;
+     }
+   else
+     {
+        if (!_ecore_win32_event_char_get(LOWORD(msg->window_param),
+                                         (char **)&e->keyname,
+                                         (char **)&e->key,
+                                         (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+
+ store_key:
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+   e->timestamp = msg->time;
+
+   _ecore_win32_event_last_time = e->timestamp;
+
+   ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_win32_event_free_key_up, NULL);
+}
+
+void
+_ecore_win32_event_handle_button_press(Ecore_Win32_Callback_Data *msg,
+                                       int                        button)
+{
+   Ecore_Win32_Window *window;
+
+   INF("mouse button pressed");
+
+   window = (Ecore_Win32_Window *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   if (button > 3)
+     {
+        Ecore_Event_Mouse_Wheel *e;
+
+        e = (Ecore_Event_Mouse_Wheel *)calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
+        if (!e) return;
+
+        e->window = (Ecore_Window)window;
+        e->direction = 0;
+        /* wheel delta is positive or negative, never 0 */
+        e->z = GET_WHEEL_DELTA_WPARAM(msg->window_param) > 0 ? -1 : 1;
+        e->x = GET_X_LPARAM(msg->data_param);
+        e->y = GET_Y_LPARAM(msg->data_param);
+        e->timestamp = msg->time;
+
+        _ecore_win32_event_last_time = e->timestamp;
+        _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+        ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
+     }
+   else
+     {
+       {
+          Ecore_Event_Mouse_Move *e;
+
+          e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+          if (!e) return;
+
+          e->window = (Ecore_Window)window;
+          e->x = GET_X_LPARAM(msg->data_param);
+          e->y = GET_Y_LPARAM(msg->data_param);
+          e->timestamp = msg->time;
+
+          _ecore_win32_event_last_time = e->timestamp;
+          _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+          ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+       }
+
+       {
+          Ecore_Event_Mouse_Button *e;
+
+          if (_ecore_win32_mouse_down_did_triple)
+            {
+               _ecore_win32_mouse_down_last_window = NULL;
+               _ecore_win32_mouse_down_last_last_window = NULL;
+               _ecore_win32_mouse_down_last_time = 0;
+               _ecore_win32_mouse_down_last_last_time = 0;
+            }
+
+          e = (Ecore_Event_Mouse_Button *)calloc(1, sizeof(Ecore_Event_Mouse_Button));
+          if (!e) return;
+
+          e->window = (Ecore_Window)window;
+          e->buttons = button;
+          e->x = GET_X_LPARAM(msg->data_param);
+          e->y = GET_Y_LPARAM(msg->data_param);
+          e->timestamp = msg->time;
+
+          if (((e->timestamp - _ecore_win32_mouse_down_last_time) <= (long)(1000 * _ecore_win32_double_click_time)) &&
+              (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_window))
+            e->double_click = 1;
+
+          if (((e->timestamp - _ecore_win32_mouse_down_last_last_time) <= (long)(2 * 1000 * _ecore_win32_double_click_time)) &&
+              (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_window) &&
+              (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_last_window))
+            {
+               e->triple_click = 1;
+               _ecore_win32_mouse_down_did_triple = 1;
+            }
+          else
+            _ecore_win32_mouse_down_did_triple = 0;
+
+          if (!e->double_click && !e->triple_click)
+            _ecore_win32_mouse_up_count = 0;
+
+          _ecore_win32_event_last_time = e->timestamp;
+          _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+          if (!_ecore_win32_mouse_down_did_triple)
+            {
+               _ecore_win32_mouse_down_last_last_window = _ecore_win32_mouse_down_last_window;
+               _ecore_win32_mouse_down_last_window = (Ecore_Win32_Window *)e->window;
+               _ecore_win32_mouse_down_last_last_time = _ecore_win32_mouse_down_last_time;
+               _ecore_win32_mouse_down_last_time = e->timestamp;
+            }
+
+          ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
+       }
+     }
+}
+
+void
+_ecore_win32_event_handle_button_release(Ecore_Win32_Callback_Data *msg,
+                                         int                        button)
+{
+   Ecore_Win32_Window *window;
+
+   INF("mouse button released");
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   {
+      Ecore_Event_Mouse_Move *e;
+
+      e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->x = GET_X_LPARAM(msg->data_param);
+      e->y = GET_Y_LPARAM(msg->data_param);
+      e->timestamp = msg->time;
+
+      _ecore_win32_event_last_time = e->timestamp;
+      _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+   }
+
+   {
+      Ecore_Event_Mouse_Button *e;
+
+      e = (Ecore_Event_Mouse_Button *)calloc(1, sizeof(Ecore_Event_Mouse_Button));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->buttons = button;
+      e->x = GET_X_LPARAM(msg->data_param);
+      e->y = GET_Y_LPARAM(msg->data_param);
+      e->timestamp = msg->time;
+
+      _ecore_win32_mouse_up_count++;
+
+      if ((_ecore_win32_mouse_up_count >= 2) &&
+          ((e->timestamp - _ecore_win32_mouse_down_last_time) <= (long)(1000 * _ecore_win32_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_window))
+        e->double_click = 1;
+
+      if ((_ecore_win32_mouse_up_count >= 3) &&
+          ((e->timestamp - _ecore_win32_mouse_down_last_last_time) <= (long)(2 * 1000 * _ecore_win32_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_window) &&
+          (e->window == (Ecore_Window)_ecore_win32_mouse_down_last_last_window))
+        e->triple_click = 1;
+
+      _ecore_win32_event_last_time = e->timestamp;
+      _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_win32_event_handle_motion_notify(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   INF("mouse moved");
+
+   e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+   if (!e) return;
+
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   e->x = GET_X_LPARAM(msg->data_param);
+   e->y = GET_Y_LPARAM(msg->data_param);
+   e->timestamp = msg->time;
+
+   ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_enter_notify(Ecore_Win32_Callback_Data *msg)
+{
+  {
+     Ecore_Event_Mouse_Move *e;
+
+     INF("mouse in");
+
+     e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+     if (!e) return;
+
+     e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+     e->x = msg->x;
+     e->y = msg->y;
+     e->timestamp = msg->time;
+
+     _ecore_win32_event_last_time = e->timestamp;
+     _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+     ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+  }
+
+  {
+     Ecore_Win32_Event_Mouse_In *e;
+
+     e = (Ecore_Win32_Event_Mouse_In *)calloc(1, sizeof(Ecore_Win32_Event_Mouse_In));
+     if (!e) return;
+
+     e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+     e->x = msg->x;
+     e->y = msg->y;
+     e->time = msg->time ;
+
+     _ecore_win32_event_last_time = e->time;
+
+     ecore_event_add(ECORE_WIN32_EVENT_MOUSE_IN, e, NULL, NULL);
+  }
+}
+
+void
+_ecore_win32_event_handle_leave_notify(Ecore_Win32_Callback_Data *msg)
+{
+  {
+     Ecore_Event_Mouse_Move *e;
+
+     INF("mouse out");
+
+     e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+     if (!e) return;
+
+     e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+     e->x = msg->x;
+     e->y = msg->y;
+     e->timestamp = msg->time;
+
+     _ecore_win32_event_last_time = e->timestamp;
+     _ecore_win32_event_last_window = (Ecore_Win32_Window *)e->window;
+
+     ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+  }
+
+  {
+     Ecore_Win32_Event_Mouse_Out *e;
+
+     e = (Ecore_Win32_Event_Mouse_Out *)calloc(1, sizeof(Ecore_Win32_Event_Mouse_Out));
+     if (!e) return;
+
+     e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+     e->x = msg->x;
+     e->y = msg->y;
+     e->time = msg->time;
+
+     _ecore_win32_event_last_time = e->time;
+
+     ecore_event_add(ECORE_WIN32_EVENT_MOUSE_OUT, e, NULL, NULL);
+  }
+}
+
+void
+_ecore_win32_event_handle_focus_in(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Focus_In *e;
+
+   INF("focus in");
+
+   e = (Ecore_Win32_Event_Window_Focus_In *)calloc(1, sizeof(Ecore_Win32_Event_Window_Focus_In));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+   _ecore_win32_event_last_time = e->time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_focus_out(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Focus_Out *e;
+
+   INF("focus out");
+
+   e = (Ecore_Win32_Event_Window_Focus_Out *)calloc(1, sizeof(Ecore_Win32_Event_Window_Focus_Out));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+   _ecore_win32_event_last_time = e->time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_expose(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Damage *e;
+
+   INF("window expose");
+
+   e = (Ecore_Win32_Event_Window_Damage *)calloc(1, sizeof(Ecore_Win32_Event_Window_Damage));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->x = msg->update.left;
+   e->y = msg->update.top;
+   e->width = msg->update.right - msg->update.left;
+   e->height = msg->update.bottom - msg->update.top;
+
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_create_notify(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Create *e;
+
+   INF("window create notify");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Create));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_CREATE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_destroy_notify(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Destroy *e;
+
+   INF("window destroy notify");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Destroy));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+   if (e->window == _ecore_win32_event_last_window) _ecore_win32_event_last_window = NULL;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_DESTROY, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_map_notify(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Show *e;
+
+   INF("window map notify");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Show));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_SHOW, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_unmap_notify(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Hide *e;
+
+   INF("window unmap notify");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Hide));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_HIDE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_configure_notify(Ecore_Win32_Callback_Data *msg)
+{
+   WINDOWINFO                          wi;
+   Ecore_Win32_Event_Window_Configure *e;
+   WINDOWPOS                          *window_pos;
+
+   INF("window configure notify");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Configure));
+   if (!e) return;
+
+   window_pos = (WINDOWPOS *)msg->data_param;
+   wi.cbSize = sizeof(WINDOWINFO);
+   if (!GetWindowInfo(window_pos->hwnd, &wi))
+     {
+        free(e);
+        return;
+     }
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   e->abovewin = (void *)GetWindowLong(window_pos->hwndInsertAfter, GWL_USERDATA);
+   e->x = wi.rcClient.left;
+   e->y = wi.rcClient.top;
+   e->width = wi.rcClient.right - wi.rcClient.left;
+   e->height = wi.rcClient.bottom - wi.rcClient.top;
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_CONFIGURE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_resize(Ecore_Win32_Callback_Data *msg)
+{
+   RECT                             rect;
+   Ecore_Win32_Event_Window_Resize *e;
+
+   INF("window resize");
+
+   if (!GetClientRect(msg->window, &rect))
+     return;
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Resize));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   e->width = rect.right - rect.left;
+   e->height = rect.bottom - rect.top;
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_RESIZE, e, NULL, NULL);
+}
+
+void
+_ecore_win32_event_handle_delete_request(Ecore_Win32_Callback_Data *msg)
+{
+   Ecore_Win32_Event_Window_Delete_Request *e;
+
+   INF("window delete request");
+
+   e = calloc(1, sizeof(Ecore_Win32_Event_Window_Delete_Request));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   e->time = _ecore_win32_event_last_time;
+
+   ecore_event_add(ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
+}
+
+
+/***** Private functions definitions *****/
+
+static void
+_ecore_win32_event_free_key_down(void *data __UNUSED__,
+                                 void *ev)
+{
+   Ecore_Event_Key *e;
+
+   e = ev;
+   if (e->keyname) free((char *)e->keyname);
+   if (e->key) free((char *)e->key);
+   if (e->string) free((char *)e->string);
+   free(e);
+}
+
+static void
+_ecore_win32_event_free_key_up(void *data __UNUSED__,
+                               void *ev)
+{
+   Ecore_Event_Key *e;
+
+   e = ev;
+   if (e->keyname) free((char *)e->keyname);
+   if (e->key) free((char *)e->key);
+   if (e->string) free((char *)e->string);
+   free(e);
+}
+
+static int
+_ecore_win32_event_keystroke_get(int    key,
+                                 int    is_extended,
+                                 char **keyname,
+                                 char **keysymbol,
+                                 char **keycompose)
+{
+  char *kn;
+  char *ks;
+  char *kc;
+
+  *keyname = NULL;
+  *keysymbol = NULL;
+  *keycompose = NULL;
+
+   switch (key)
+     {
+       /* Keystroke */
+     case VK_PRIOR:
+       if (is_extended)
+         {
+            kn = "Prior";
+            ks = "Prior";
+            kc = "Prior";
+         }
+       else
+         {
+            kn = "KP_Prior";
+            ks = "KP_9";
+            kc = "KP_Prior";
+         }
+       break;
+     case VK_NEXT:
+       if (is_extended)
+         {
+            kn = "Next";
+            ks = "Next";
+            kc = "Next";
+         }
+       else
+         {
+            kn = "KP_Next";
+            ks = "KP_3";
+            kc = "KP_Next";
+         }
+       break;
+     case VK_END:
+       if (is_extended)
+         {
+            kn = "End";
+            ks = "End";
+            kc = "End";
+         }
+       else
+         {
+            kn = "KP_End";
+            ks = "KP_1";
+            kc = "KP_End";
+         }
+       break;
+     case VK_HOME:
+       if (is_extended)
+         {
+            kn = "Home";
+            ks = "Home";
+            kc = "Home";
+         }
+       else
+         {
+            kn = "KP_Home";
+            ks = "KP_7";
+            kc = "KP_Home";
+         }
+       break;
+     case VK_LEFT:
+       if (is_extended)
+         {
+            kn = "Left";
+            ks = "Left";
+            kc = "Left";
+         }
+       else
+         {
+            kn = "KP_Left";
+            ks = "KP_4";
+            kc = "KP_Left";
+         }
+       break;
+     case VK_UP:
+       if (is_extended)
+         {
+            kn = "Up";
+            ks = "Up";
+            kc = "Up";
+         }
+       else
+         {
+            kn = "KP_Up";
+            ks = "KP_8";
+            kc = "KP_Up";
+         }
+       break;
+     case VK_RIGHT:
+       if (is_extended)
+         {
+           kn = "Right";
+           ks = "Right";
+           kc = "Right";
+         }
+       else
+         {
+           kn = "KP_Right";
+           ks = "KP_6";
+           kc = "KP_Right";
+         }
+       break;
+     case VK_DOWN:
+       if (is_extended)
+         {
+           kn = "Down";
+           ks = "Down";
+           kc = "Down";
+         }
+       else
+         {
+           kn = "KP_Down";
+           ks = "KP_2";
+           kc = "KP_Down";
+         }
+       break;
+     case VK_INSERT:
+       if (is_extended)
+         {
+           kn = "Insert";
+           ks = "Insert";
+           kc = "Insert";
+         }
+       else
+         {
+           kn = "KP_Insert";
+           ks = "KP_0";
+           kc = "KP_Insert";
+         }
+       break;
+     case VK_DELETE:
+       if (is_extended)
+         {
+           kn = "Delete";
+           ks = "Delete";
+           kc = "Delete";
+         }
+       else
+         {
+           kn = "KP_Delete";
+           ks = "KP_Decimal";
+           kc = "KP_Delete";
+         }
+       break;
+     case VK_F1:
+       kn = "F1";
+       ks = "F1";
+       kc = "";
+       break;
+     case VK_F2:
+       kn = "F2";
+       ks = "F2";
+       kc = "";
+       break;
+     case VK_F3:
+       kn = "F3";
+       ks = "F3";
+       kc = "";
+       break;
+     case VK_F4:
+       kn = "F4";
+       ks = "F4";
+       kc = "";
+       break;
+     case VK_F5:
+       kn = "F5";
+       ks = "F5";
+       kc = "";
+       break;
+     case VK_F6:
+       kn = "F6";
+       ks = "F6";
+       kc = "";
+       break;
+     case VK_F7:
+       kn = "F7";
+       ks = "F7";
+       kc = "";
+       break;
+     case VK_F8:
+       kn = "F8";
+       ks = "F8";
+       kc = "";
+       break;
+     case VK_F9:
+       kn = "F9";
+       ks = "F9";
+       kc = "";
+       break;
+     case VK_F10:
+       kn = "F10";
+       ks = "F10";
+       kc = "";
+       break;
+     case VK_F11:
+       kn = "F11";
+       ks = "F11";
+       kc = "";
+       break;
+     case VK_F12:
+       kn = "F12";
+       ks = "F12";
+       kc = "";
+       break;
+     case VK_F13:
+       kn = "F13";
+       ks = "F13";
+       kc = "";
+       break;
+     case VK_F14:
+       kn = "F14";
+       ks = "F14";
+       kc = "";
+       break;
+     case VK_F15:
+       kn = "F15";
+       ks = "F15";
+       kc = "";
+       break;
+     case VK_F16:
+       kn = "F16";
+       ks = "F16";
+       kc = "";
+       break;
+     case VK_F17:
+       kn = "F17";
+       ks = "F17";
+       kc = "";
+       break;
+     case VK_F18:
+       kn = "F18";
+       ks = "F18";
+       kc = "";
+       break;
+     case VK_F19:
+       kn = "F19";
+       ks = "F19";
+       kc = "";
+       break;
+     case VK_F20:
+       kn = "F20";
+       ks = "F20";
+       kc = "";
+       break;
+     case VK_F21:
+       kn = "F21";
+       ks = "F21";
+       kc = "";
+       break;
+     case VK_F22:
+       kn = "F22";
+       ks = "F22";
+       kc = "";
+       break;
+     case VK_F23:
+       kn = "F23";
+       ks = "F23";
+       kc = "";
+       break;
+     case VK_F24:
+       kn = "F24";
+       ks = "F24";
+       kc = "";
+       break;
+     default:
+       /* other non keystroke characters */
+       return 0;
+     }
+   *keyname = strdup(kn);
+   if (!*keyname) return 0;
+   *keysymbol = strdup(ks);
+   if (!*keysymbol)
+     {
+        free(*keyname);
+        *keyname = NULL;
+        return 0;
+     }
+   *keycompose = strdup(kc);
+   if (!*keycompose)
+     {
+        free(*keyname);
+        free(*keysymbol);
+        *keyname = NULL;
+        *keysymbol = NULL;
+        return 0;
+     }
+
+   return 1;
+}
+
+static int
+_ecore_win32_event_char_get(int    key,
+                            char **keyname,
+                            char **keysymbol,
+                            char **keycompose)
+{
+  char kn[32];
+  char ks[32];
+  char kc[32];
+
+  *keyname = NULL;
+  *keysymbol = NULL;
+  *keycompose = NULL;
+
+   switch (key)
+     {
+     case VK_BACK:
+       strncpy(kn, "BackSpace", 32);
+       strncpy(ks, "BackSpace", 32);
+       strncpy(kc, "BackSpace", 32);
+       break;
+     case VK_TAB:
+       strncpy(kn, "Tab", 32);
+       strncpy(ks, "ISO_Left_Tab", 32);
+       strncpy(kc, "Tab", 32);
+       break;
+     case 0x0a:
+       /* Line feed (Shift + Enter) */
+       strncpy(kn, "LineFeed", 32);
+       strncpy(ks, "LineFeed", 32);
+       strncpy(kc, "LineFeed", 32);
+       break;
+     case VK_RETURN:
+       strncpy(kn, "Return", 32);
+       strncpy(ks, "Return", 32);
+       strncpy(kc, "Return", 32);
+       break;
+     case VK_ESCAPE:
+       strncpy(kn, "Escape", 32);
+       strncpy(ks, "Escape", 32);
+       strncpy(kc, "Escape", 32);
+       break;
+     default:
+       /* displayable characters */
+       printf (" * key : %d\n", key);
+       kn[0] = (TCHAR)key;
+       kn[1] = '\0';
+       ks[0] = (TCHAR)key;
+       ks[1] = '\0';
+       kc[0] = (TCHAR)key;
+       kc[1] = '\0';
+       break;
+     }
+   *keyname = strdup(kn);
+   if (!*keyname) return 0;
+   *keysymbol = strdup(ks);
+   if (!*keysymbol)
+     {
+        free(*keyname);
+        *keyname = NULL;
+        return 0;
+     }
+   *keycompose = strdup(kc);
+   if (!*keycompose)
+     {
+        free(*keyname);
+        free(*keysymbol);
+        *keyname = NULL;
+        *keysymbol = NULL;
+        return 0;
+     }
+
+   return 1;
+}
diff --git a/src/lib/ecore_win32/ecore_win32_private.h b/src/lib/ecore_win32/ecore_win32_private.h
new file mode 100644 (file)
index 0000000..e824dac
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef __ECORE_WIN32_PRIVATE_H__
+#define __ECORE_WIN32_PRIVATE_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* logging messages macros */
+extern int _ecore_win32_log_dom_global;
+
+#ifdef ECORE_WIN32_DEFAULT_LOG_COLOR
+# undef ECORE_WIN32_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_WIN32_DEFAULT_LOG_COLOR EINA_COLOR_LIGHTBLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_win32_log_dom_global , __VA_ARGS__)
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_win32_log_dom_global , __VA_ARGS__)
+
+#ifdef INF
+#undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_win32_log_dom_global , __VA_ARGS__)
+
+#define ECORE_WIN32_WINDOW_CLASS "Ecore_Win32_Window_Class"
+
+typedef struct _Ecore_Win32_Callback_Data Ecore_Win32_Callback_Data;
+
+struct _Ecore_Win32_Callback_Data
+{
+   RECT         update;
+   HWND         window;
+   unsigned int message;
+   WPARAM       window_param;
+   LPARAM       data_param;
+   long         time;
+   int          x;
+   int          y;
+};
+
+struct _Ecore_Win32_Window
+{
+   HWND                   window;
+
+   DWORD                  style;          /* used to go fullscreen to normal */
+   RECT                   rect;           /* used to go fullscreen to normal */
+
+   unsigned int           min_width;
+   unsigned int           min_height;
+   unsigned int           max_width;
+   unsigned int           max_height;
+   unsigned int           base_width;
+   unsigned int           base_height;
+   unsigned int           step_width;
+   unsigned int           step_height;
+
+   struct {
+      unsigned int        iconified         : 1;
+      unsigned int        modal             : 1;
+      unsigned int        sticky            : 1;
+      unsigned int        maximized_vert    : 1;
+      unsigned int        maximized_horz    : 1;
+      unsigned int        shaded            : 1;
+      unsigned int        hidden            : 1;
+      unsigned int        fullscreen        : 1;
+      unsigned int        above             : 1;
+      unsigned int        below             : 1;
+      unsigned int        demands_attention : 1;
+   } state;
+
+   struct {
+      unsigned int        desktop : 1;
+      unsigned int        dock    : 1;
+      unsigned int        toolbar : 1;
+      unsigned int        menu    : 1;
+      unsigned int        utility : 1;
+      unsigned int        splash  : 1;
+      unsigned int        dialog  : 1;
+      unsigned int        normal  : 1;
+   } type;
+
+   unsigned int           pointer_is_in : 1;
+   unsigned int           borderless    : 1;
+   unsigned int           iconified     : 1;
+   unsigned int           fullscreen    : 1;
+
+   struct {
+      unsigned short width;
+      unsigned short height;
+      unsigned char *mask;
+      unsigned int   enabled : 1;
+      unsigned int   layered : 1;
+   } shape;
+
+   void *dnd_drop_target;
+};
+
+
+extern HINSTANCE           _ecore_win32_instance;
+extern double              _ecore_win32_double_click_time;
+extern long                _ecore_win32_event_last_time;
+extern Ecore_Win32_Window *_ecore_win32_event_last_window;
+
+
+void  _ecore_win32_event_handle_key_press(Ecore_Win32_Callback_Data *msg, int is_keystroke);
+void  _ecore_win32_event_handle_key_release(Ecore_Win32_Callback_Data *msg, int is_keystroke);
+void  _ecore_win32_event_handle_button_press(Ecore_Win32_Callback_Data *msg, int button);
+void  _ecore_win32_event_handle_button_release(Ecore_Win32_Callback_Data *msg, int button);
+void  _ecore_win32_event_handle_motion_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_enter_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_leave_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_focus_in(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_focus_out(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_expose(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_create_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_destroy_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_map_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_unmap_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_configure_notify(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_resize(Ecore_Win32_Callback_Data *msg);
+void  _ecore_win32_event_handle_delete_request(Ecore_Win32_Callback_Data *msg);
+
+void *_ecore_win32_dnd_data_object_new(void *fmtetc, void *stgmeds, int count);
+void _ecore_win32_dnd_data_object_free(void *data_object);
+void *_ecore_win32_dnd_drop_source_new();
+void _ecore_win32_dnd_drop_source_free(void *drop_source);
+void *_ecore_win32_dnd_register_drop_window(HWND hwnd,
+                                            Ecore_Win32_Dnd_DropTarget_Callback callback, void *ptr);
+void _ecore_win32_dnd_unregister_drop_window(HWND hwnd, void *drop_target);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __ECORE_WIN32_PRIVATE_H__ */
diff --git a/src/lib/ecore_win32/ecore_win32_window.c b/src/lib/ecore_win32/ecore_win32_window.c
new file mode 100644 (file)
index 0000000..618b516
--- /dev/null
@@ -0,0 +1,1217 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>   /* for printf */
+
+#define _WIN32_WINNT 0x0500  // For WS_EX_LAYERED
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Eina.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+
+/***** Private declarations *****/
+
+
+typedef enum _Ecore_Win32_Window_Z_Order Ecore_Win32_Window_Z_Order;
+enum _Ecore_Win32_Window_Z_Order
+{
+  ECORE_WIN32_WINDOW_Z_ORDER_BOTTOM,
+  ECORE_WIN32_WINDOW_Z_ORDER_NOTOPMOST,
+  ECORE_WIN32_WINDOW_Z_ORDER_TOP,
+  ECORE_WIN32_WINDOW_Z_ORDER_TOPMOST
+};
+
+static Ecore_Win32_Window *ecore_win32_window_internal_new(Ecore_Win32_Window *parent,
+                                                           int                 x,
+                                                           int                 y,
+                                                           int                 width,
+                                                           int                 height,
+                                                           DWORD               style);
+
+
+/***** API *****/
+
+Ecore_Win32_Window *
+ecore_win32_window_new(Ecore_Win32_Window *parent,
+                       int                 x,
+                       int                 y,
+                       int                 width,
+                       int                 height)
+{
+   INF("creating window with border");
+
+   return ecore_win32_window_internal_new(parent,
+                                          x, y,
+                                          width, height,
+                                          WS_OVERLAPPEDWINDOW | WS_SIZEBOX);
+}
+
+/* simulate X11 override windows */
+Ecore_Win32_Window *
+ecore_win32_window_override_new(Ecore_Win32_Window *parent,
+                                int                 x,
+                                int                 y,
+                                int                 width,
+                                int                 height)
+{
+   INF("creating window without border");
+
+   return ecore_win32_window_internal_new(parent,
+                                          x, y,
+                                          width, height,
+                                          WS_POPUP);
+}
+
+void
+ecore_win32_window_free(Ecore_Win32_Window *window)
+{
+   struct _Ecore_Win32_Window *wnd = window;
+
+   if (!window) return;
+
+   INF("destroying window");
+
+   if (wnd->shape.mask != NULL)
+      free(wnd->shape.mask);
+
+   DestroyWindow(((struct _Ecore_Win32_Window *)window)->window);
+   free(window);
+}
+
+void *
+ecore_win32_window_hwnd_get(Ecore_Win32_Window *window)
+{
+   if (!window) return NULL;
+
+   return ((struct _Ecore_Win32_Window *)window)->window;
+}
+
+/*
+void
+ecore_win32_window_configure(Ecore_Win32_Window        *window,
+                             Ecore_Win32_Window_Z_Order order,
+                             int                        x,
+                             int                        y,
+                             int                        width,
+                             int                        height)
+{
+  HWND w;
+
+  switch (order)
+    {
+    case ECORE_WIN32_WINDOW_Z_ORDER_BOTTOM:
+      w = HWND_BOTTOM;
+      break;
+    case ECORE_WIN32_WINDOW_Z_ORDER_NOTOPMOST:
+      w = HWND_NOTOPMOST;
+      break;
+    case ECORE_WIN32_WINDOW_Z_ORDER_TOP:
+      w = HWND_TOP;
+      break;
+    case ECORE_WIN32_WINDOW_Z_ORDER_TOPMOST:
+      w = HWND_TOPMOST;
+      break;
+    default:
+      return;
+    }
+  SetWindowPos((struct _Ecore_Win32_Window *)window->window, w, x, y, width, height, ???);
+}
+*/
+
+void
+ecore_win32_window_move(Ecore_Win32_Window *window,
+                        int                 x,
+                        int                 y)
+{
+   RECT rect;
+   HWND w;
+
+   if (!window) return;
+
+   INF("moving window (%dx%d)", x, y);
+
+   w = ((struct _Ecore_Win32_Window *)window)->window;
+   if (!GetWindowRect(w, &rect))
+     {
+        ERR("GetWindowRect() failed");
+        return;
+     }
+
+   if (!MoveWindow(w, x, y,
+                   rect.right - rect.left,
+                   rect.bottom - rect.top,
+                   TRUE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_win32_window_resize(Ecore_Win32_Window *window,
+                          int                 width,
+                          int                 height)
+{
+   RECT                        rect;
+   struct _Ecore_Win32_Window *w;
+   DWORD                       style;
+   int                         x;
+   int                         y;
+
+   if (!window) return;
+
+   INF("resizing window (%dx%d)", width, height);
+
+   w = (struct _Ecore_Win32_Window *)window;
+   if (!GetWindowRect(w->window, &rect))
+     {
+        ERR("GetWindowRect() failed");
+        return;
+     }
+
+   x = rect.left;
+   y = rect.top;
+   rect.left = 0;
+   rect.top = 0;
+/*    if (width < w->min_width) width = w->min_width; */
+/*    if (width > w->max_width) width = w->max_width; */
+/*    printf ("ecore_win32_window_resize 1 : %d %d %d\n", w->min_height, w->max_height, height); */
+/*    if (height < w->min_height) height = w->min_height; */
+/*    printf ("ecore_win32_window_resize 2 : %d %d\n", w->max_height, height); */
+/*    if (height > w->max_height) height = w->max_height; */
+/*    printf ("ecore_win32_window_resize 3 : %d %d\n", w->max_height, height); */
+   rect.right = width;
+   rect.bottom = height;
+   if (!(style = GetWindowLong(w->window, GWL_STYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!AdjustWindowRect(&rect, style, FALSE))
+     {
+        ERR("AdjustWindowRect() failed");
+        return;
+     }
+
+   if (!MoveWindow(w->window, x, y,
+                   rect.right - rect.left,
+                   rect.bottom - rect.top,
+                   TRUE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_win32_window_move_resize(Ecore_Win32_Window *window,
+                               int                 x,
+                               int                 y,
+                               int                 width,
+                               int                 height)
+{
+   RECT                        rect;
+   struct _Ecore_Win32_Window *w;
+   DWORD                       style;
+
+   if (!window) return;
+
+   INF("moving and resizing window (%dx%d %dx%d)", x, y, width, height);
+
+   w = ((struct _Ecore_Win32_Window *)window);
+   rect.left = 0;
+   rect.top = 0;
+   if ((unsigned int)width < w->min_width) width = w->min_width;
+   if ((unsigned int)width > w->max_width) width = w->max_width;
+   if ((unsigned int)height < w->min_height) height = w->min_height;
+   if ((unsigned int)height > w->max_height) height = w->max_height;
+   rect.right = width;
+   rect.bottom = height;
+   if (!(style = GetWindowLong(w->window, GWL_STYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!AdjustWindowRect(&rect, style, FALSE))
+     {
+        ERR("AdjustWindowRect() failed");
+        return;
+     }
+
+   if (!MoveWindow(w->window, x, y,
+                   rect.right - rect.left,
+                   rect.bottom - rect.top,
+                   TRUE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_win32_window_geometry_get(Ecore_Win32_Window *window,
+                                int                *x,
+                                int                *y,
+                                int                *width,
+                                int                *height)
+{
+   RECT rect;
+   int  w;
+   int  h;
+
+   INF("getting window geometry");
+
+   if (!window)
+     {
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = GetSystemMetrics(SM_CXSCREEN);
+        if (height) *height = GetSystemMetrics(SM_CYSCREEN);
+
+        return;
+     }
+
+   if (!GetClientRect(((struct _Ecore_Win32_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetClientRect() failed");
+
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = 0;
+        if (height) *height = 0;
+
+        return;
+     }
+
+   w = rect.right - rect.left;
+   h = rect.bottom - rect.top;
+
+   if (!GetWindowRect(((struct _Ecore_Win32_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetWindowRect() failed");
+
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = 0;
+        if (height) *height = 0;
+
+        return;
+     }
+
+   if (x) *x = rect.left;
+   if (y) *y = rect.top;
+   if (width) *width = w;
+   if (height) *height = h;
+}
+
+void
+ecore_win32_window_size_get(Ecore_Win32_Window *window,
+                            int                *width,
+                            int                *height)
+{
+   RECT rect;
+
+   INF("getting window size");
+
+   if (!window)
+     {
+        if (width) *width = GetSystemMetrics(SM_CXSCREEN);
+        if (height) *height = GetSystemMetrics(SM_CYSCREEN);
+
+        return;
+     }
+
+   if (!GetClientRect(((struct _Ecore_Win32_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetClientRect() failed");
+
+        if (width) *width = 0;
+        if (height) *height = 0;
+     }
+
+   if (width) *width = rect.right - rect.left;
+   if (height) *height = rect.bottom - rect.top;
+}
+
+void
+ecore_win32_window_size_min_set(Ecore_Win32_Window *window,
+                                unsigned int        min_width,
+                                unsigned int        min_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   printf ("ecore_win32_window_size_min_set : %p  %d %d\n", window, min_width, min_height);
+   w = (struct _Ecore_Win32_Window *)window;
+   w->min_width = min_width;
+   w->min_height = min_height;
+}
+
+void
+ecore_win32_window_size_min_get(Ecore_Win32_Window *window,
+                                unsigned int       *min_width,
+                                unsigned int       *min_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   printf ("ecore_win32_window_size_min_get : %p  %d %d\n", window, w->min_width, w->min_height);
+   if (min_width) *min_width = w->min_width;
+   if (min_height) *min_height = w->min_height;
+}
+
+void
+ecore_win32_window_size_max_set(Ecore_Win32_Window *window,
+                                unsigned int        max_width,
+                                unsigned int        max_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   printf ("ecore_win32_window_size_max_set : %p  %d %d\n", window, max_width, max_height);
+   w = (struct _Ecore_Win32_Window *)window;
+   w->max_width = max_width;
+   w->max_height = max_height;
+}
+
+void
+ecore_win32_window_size_max_get(Ecore_Win32_Window *window,
+                                unsigned int       *max_width,
+                                unsigned int       *max_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   printf ("ecore_win32_window_size_max_get : %p  %d %d\n", window, w->max_width, w->max_height);
+   if (max_width) *max_width = w->max_width;
+   if (max_height) *max_height = w->max_height;
+}
+
+void
+ecore_win32_window_size_base_set(Ecore_Win32_Window *window,
+                                 unsigned int        base_width,
+                                 unsigned int        base_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   printf ("ecore_win32_window_size_base_set : %p  %d %d\n", window, base_width, base_height);
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   w->base_width = base_width;
+   w->base_height = base_height;
+}
+
+void
+ecore_win32_window_size_base_get(Ecore_Win32_Window *window,
+                                 unsigned int       *base_width,
+                                 unsigned int       *base_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   printf ("ecore_win32_window_size_base_get : %p  %d %d\n", window, w->base_width, w->base_height);
+   if (base_width) *base_width = w->base_width;
+   if (base_height) *base_height = w->base_height;
+}
+
+void
+ecore_win32_window_size_step_set(Ecore_Win32_Window *window,
+                                 unsigned int        step_width,
+                                 unsigned int        step_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   printf ("ecore_win32_window_size_step_set : %p  %d %d\n", window, step_width, step_height);
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   w->step_width = step_width;
+   w->step_height = step_height;
+}
+
+void
+ecore_win32_window_size_step_get(Ecore_Win32_Window *window,
+                                 unsigned int       *step_width,
+                                 unsigned int       *step_height)
+{
+   struct _Ecore_Win32_Window *w;
+
+   if (!window) return;
+
+   w = (struct _Ecore_Win32_Window *)window;
+   printf ("ecore_win32_window_size_step_get : %p  %d %d\n", window, w->step_width, w->step_height);
+   if (step_width) *step_width = w->step_width;
+   if (step_height) *step_height = w->step_height;
+}
+
+void
+ecore_win32_window_shape_set(Ecore_Win32_Window *window,
+                             unsigned short      width,
+                             unsigned short      height,
+                             unsigned char      *mask)
+{
+   struct _Ecore_Win32_Window *wnd;
+   HRGN                        rgn;
+   int                         x;
+   int                         y;
+   OSVERSIONINFO               version_info;
+
+   if (window == NULL)
+      return;
+
+   wnd = (struct _Ecore_Win32_Window *)window;
+
+   if (mask == NULL)
+     {
+        wnd->shape.enabled = 0;
+        if (wnd->shape.layered != 0)
+          {
+             wnd->shape.layered = 0;
+#if defined(WS_EX_LAYERED)
+             SetLastError(0);
+             if (!SetWindowLongPtr(wnd->window, GWL_EXSTYLE,
+                                   GetWindowLong(wnd->window, GWL_EXSTYLE) & (~WS_EX_LAYERED)) &&
+                 (GetLastError() != 0))
+               {
+                  ERR("SetWindowLongPtr() failed");
+                  return;
+               }
+             if (!RedrawWindow(wnd->window, NULL, NULL,
+                               RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN))
+               {
+                  ERR("RedrawWindow() failed");
+                  return;
+               }
+#endif
+          }
+        else
+          if (!SetWindowRgn(wnd->window, NULL, TRUE))
+            {
+               ERR("SetWindowRgn() failed");
+            }
+        return;
+     }
+
+   if (width == 0 || height == 0)
+     return;
+
+   wnd->shape.enabled = 1;
+
+   if (width != wnd->shape.width || height != wnd->shape.height)
+     {
+       wnd->shape.width = width;
+       wnd->shape.height = height;
+       if (wnd->shape.mask != NULL)
+         {
+           free(wnd->shape.mask);
+           wnd->shape.mask = NULL;
+         }
+       wnd->shape.mask = malloc(width * height);
+     }
+   memcpy(wnd->shape.mask, mask, width * height);
+
+   wnd->shape.layered = 0;
+
+#if defined(WS_EX_LAYERED)
+   version_info.dwOSVersionInfoSize = sizeof(version_info);
+   if (GetVersionEx(&version_info) == TRUE && version_info.dwMajorVersion == 5)
+     {
+       SetLastError(0);
+       if (!SetWindowLongPtr(wnd->window, GWL_EXSTYLE,
+                             GetWindowLong(wnd->window, GWL_EXSTYLE) | WS_EX_LAYERED) &&
+           (GetLastError() != 0))
+            {
+               ERR("SetWindowLongPtr() failed");
+               return;
+            }
+       wnd->shape.layered = 1;
+       return;
+     }
+#endif
+
+   if (!(rgn = CreateRectRgn(0, 0, 0, 0)))
+     {
+        ERR("CreateRectRgn() failed");
+        return;
+     }
+   for (y = 0; y < height; y++)
+     {
+        HRGN rgnLine;
+
+        if (!(rgnLine = CreateRectRgn(0, 0, 0, 0)))
+          {
+             ERR("CreateRectRgn() failed");
+             return;
+          }
+        for (x = 0; x < width; x++)
+          {
+             if (mask[y * width + x] > 0)
+               {
+                  HRGN rgnDot;
+
+                  if (!(rgnDot = CreateRectRgn(x, y, x + 1, y + 1)))
+                    {
+                       ERR("CreateRectRgn() failed");
+                       return;
+                    }
+                  if (CombineRgn(rgnLine, rgnLine, rgnDot, RGN_OR) == ERROR)
+                    {
+                       ERR("CombineRgn() has not created a new region");
+                    }
+                  if (!DeleteObject(rgnDot))
+                    {
+                       ERR("DeleteObject() failed");
+                       return;
+                    }
+               }
+          }
+        if (CombineRgn(rgn, rgn, rgnLine, RGN_OR) == ERROR)
+          {
+             ERR("CombineRgn() has not created a new region");
+          }
+        if (!DeleteObject(rgnLine))
+          {
+             ERR("DeleteObject() failed");
+             return;
+          }
+     }
+   if (!SetWindowRgn(wnd->window, rgn, TRUE))
+     {
+        ERR("SetWindowRgn() failed");
+     }
+}
+
+void
+ecore_win32_window_show(Ecore_Win32_Window *window)
+{
+   if (!window) return;
+
+   INF("showing window");
+
+   ShowWindow(((struct _Ecore_Win32_Window *)window)->window, SW_SHOWNORMAL);
+   if (!UpdateWindow(((struct _Ecore_Win32_Window *)window)->window))
+     {
+        ERR("UpdateWindow() failed");
+     }
+}
+
+/* FIXME: seems to block the taskbar */
+void
+ecore_win32_window_hide(Ecore_Win32_Window *window)
+{
+   if (!window) return;
+
+   INF("hiding window");
+
+   ShowWindow(((struct _Ecore_Win32_Window *)window)->window, SW_HIDE);
+}
+
+void
+ecore_win32_window_raise(Ecore_Win32_Window *window)
+{
+   if (!window) return;
+
+   INF("raising window");
+
+   if (!SetWindowPos(((struct _Ecore_Win32_Window *)window)->window,
+                     HWND_TOP, 0, 0, 0, 0,
+                     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
+     {
+        ERR("SetWindowPos() failed");
+     }
+}
+
+void
+ecore_win32_window_lower(Ecore_Win32_Window *window)
+{
+   if (!window) return;
+
+   INF("lowering window");
+
+   if (!SetWindowPos(((struct _Ecore_Win32_Window *)window)->window,
+                     HWND_BOTTOM, 0, 0, 0, 0,
+                     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
+     {
+        ERR("SetWindowPos() failed");
+     }
+}
+
+void
+ecore_win32_window_title_set(Ecore_Win32_Window *window,
+                             const char         *title)
+{
+   if (!window) return;
+
+   if (!title || !title[0]) return;
+
+   INF("setting window title");
+
+   if (!SetWindowText(((struct _Ecore_Win32_Window *)window)->window, title))
+     {
+        ERR("SetWindowText() failed");
+     }
+}
+
+void
+ecore_win32_window_focus_set(Ecore_Win32_Window *window)
+{
+   if (!window) return;
+
+   INF("focusing window");
+
+   if (!SetFocus(((struct _Ecore_Win32_Window *)window)->window))
+     {
+        ERR("SetFocus() failed");
+     }
+}
+
+void
+ecore_win32_window_iconified_set(Ecore_Win32_Window *window,
+                                 int                 on)
+{
+   struct _Ecore_Win32_Window *ew;
+
+   if (!window) return;
+
+   ew = (struct _Ecore_Win32_Window *)window;
+   if (((ew->iconified) && (on)) ||
+       ((!ew->iconified) && (!on)))
+     return;
+
+   INF("iconifying window: %s", on ? "yes" : "no");
+
+   ShowWindow(ew->window, on ? SW_MINIMIZE : SW_RESTORE);
+   ew->iconified = on;
+}
+
+void
+ecore_win32_window_borderless_set(Ecore_Win32_Window *window,
+                                  int                 on)
+{
+   RECT                        rect;
+   DWORD                       style;
+   struct _Ecore_Win32_Window *ew;
+   HWND                        w;
+
+   if (!window) return;
+
+   ew = (struct _Ecore_Win32_Window *)window;
+   if (((ew->borderless) && (on)) ||
+       ((!ew->borderless) && (!on)))
+     return;
+
+   INF("setting window without border: %s", on ? "yes" : "no");
+
+   w = ew->window;
+
+   style = GetWindowLong(w, GWL_STYLE);
+   if (on)
+     {
+        if (!GetClientRect(w, &rect))
+          {
+             ERR("GetClientRect() failed");
+             return;
+          }
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_STYLE, style & ~(WS_CAPTION | WS_THICKFRAME)) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+     }
+   else
+     {
+        if (!GetWindowRect(w, &rect))
+          {
+             ERR("GetWindowRect() failed");
+             return;
+          }
+        style |= WS_CAPTION | WS_THICKFRAME;
+        if (!AdjustWindowRect (&rect, style, FALSE))
+          {
+             ERR("AdjustWindowRect() failed");
+             return;
+          }
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_STYLE, style) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+     }
+   if (!SetWindowPos(w, HWND_TOPMOST,
+                     rect.left, rect.top,
+                     rect.right - rect.left, rect.bottom - rect.top,
+                     SWP_NOMOVE | SWP_FRAMECHANGED))
+     {
+        ERR("SetWindowPos() failed");
+        return;
+     }
+   ew->borderless = on;
+}
+
+void
+ecore_win32_window_fullscreen_set(Ecore_Win32_Window *window,
+                                  int                 on)
+{
+   struct _Ecore_Win32_Window *ew;
+   HWND                        w;
+
+   if (!window) return;
+
+   ew = (struct _Ecore_Win32_Window *)window;
+   if (((ew->fullscreen) && (on)) ||
+       ((!ew->fullscreen) && (!on)))
+     return;
+
+   INF("setting fullscreen: %s", on ? "yes" : "no");
+
+   ew->fullscreen = !!on;
+   w = ew->window;
+
+   if (on)
+     {
+        DWORD style;
+
+        if (!GetWindowRect(w, &ew->rect))
+          {
+             ERR("GetWindowRect() failed");
+             return;
+          }
+        if (!(ew->style = GetWindowLong(w, GWL_STYLE)))
+          {
+             ERR("GetWindowLong() failed");
+             return;
+          }
+        style = ew->style & ~WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX;
+        style |= WS_VISIBLE | WS_POPUP;
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_STYLE, style) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_EXSTYLE, WS_EX_TOPMOST) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+        if (!SetWindowPos(w, HWND_TOPMOST, 0, 0,
+                          GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN),
+                          SWP_NOCOPYBITS | SWP_SHOWWINDOW))
+          {
+             ERR("SetWindowPos() failed");
+             return;
+          }
+     }
+   else
+     {
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_STYLE, ew->style) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+        SetLastError(0);
+        if (!SetWindowLongPtr(w, GWL_EXSTYLE, 0) && (GetLastError() != 0))
+          {
+             ERR("SetWindowLongPtr() failed");
+             return;
+          }
+        if (!SetWindowPos(w, HWND_NOTOPMOST,
+                          ew->rect.left,
+                          ew->rect.top,
+                          ew->rect.right - ew->rect.left,
+                          ew->rect.bottom - ew->rect.top,
+                          SWP_NOCOPYBITS | SWP_SHOWWINDOW))
+          {
+             ERR("SetWindowPos() failed");
+             return;
+          }
+     }
+}
+
+void
+ecore_win32_window_cursor_set(Ecore_Win32_Window *window,
+                              Ecore_Win32_Cursor *cursor)
+{
+   INF("setting cursor");
+
+   if (!SetClassLong(((struct _Ecore_Win32_Window *)window)->window,
+                     GCL_HCURSOR, (LONG)cursor))
+     {
+        ERR("SetClassLong() failed");
+     }
+}
+
+void
+ecore_win32_window_state_set(Ecore_Win32_Window       *window,
+                             Ecore_Win32_Window_State *state,
+                             unsigned int              num)
+{
+   unsigned int i;
+
+   if (!window || !state || !num)
+     return;
+
+   INF("setting cursor state");
+
+   for (i = 0; i < num; i++)
+     {
+        switch (state[i])
+          {
+          case ECORE_WIN32_WINDOW_STATE_ICONIFIED:
+            ((struct _Ecore_Win32_Window *)window)->state.iconified = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_MODAL:
+            ((struct _Ecore_Win32_Window *)window)->state.modal = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_STICKY:
+            ((struct _Ecore_Win32_Window *)window)->state.sticky = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_MAXIMIZED_VERT:
+            ((struct _Ecore_Win32_Window *)window)->state.maximized_vert = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_MAXIMIZED_HORZ:
+            ((struct _Ecore_Win32_Window *)window)->state.maximized_horz = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_MAXIMIZED:
+            ((struct _Ecore_Win32_Window *)window)->state.maximized_horz = 1;
+            ((struct _Ecore_Win32_Window *)window)->state.maximized_vert = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_SHADED:
+            ((struct _Ecore_Win32_Window *)window)->state.shaded = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_HIDDEN:
+            ((struct _Ecore_Win32_Window *)window)->state.hidden = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_FULLSCREEN:
+            ((struct _Ecore_Win32_Window *)window)->state.fullscreen = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_ABOVE:
+            ((struct _Ecore_Win32_Window *)window)->state.above = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_BELOW:
+            ((struct _Ecore_Win32_Window *)window)->state.below = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_DEMANDS_ATTENTION:
+            ((struct _Ecore_Win32_Window *)window)->state.demands_attention = 1;
+            break;
+          case ECORE_WIN32_WINDOW_STATE_UNKNOWN:
+            /* nothing to be done */
+            break;
+          }
+     }
+}
+
+void
+ecore_win32_window_state_request_send(Ecore_Win32_Window      *window,
+                                      Ecore_Win32_Window_State state,
+                                      unsigned int             set)
+{
+   struct _Ecore_Win32_Window *ew;
+   HWND                        w;
+
+   if (!window) return;
+
+   ew = (struct _Ecore_Win32_Window *)window;
+   w = ew->window;
+
+   INF("sending cursor state");
+
+   switch (state)
+     {
+      case ECORE_WIN32_WINDOW_STATE_ICONIFIED:
+         if (ew->state.iconified)
+           ecore_win32_window_iconified_set(window, set);
+         break;
+      case ECORE_WIN32_WINDOW_STATE_MODAL:
+         ew->state.modal = 1;
+         break;
+      case ECORE_WIN32_WINDOW_STATE_STICKY:
+         ew->state.sticky = 1;
+         break;
+      case ECORE_WIN32_WINDOW_STATE_MAXIMIZED_VERT:
+         if (ew->state.maximized_vert)
+           {
+              RECT rect;
+              int  y;
+              int  height;
+
+              if (!SystemParametersInfo(SPI_GETWORKAREA, 0,
+                                        &rect, 0))
+                {
+                   ERR("SystemParametersInfo() failed");
+                   break;
+                }
+              y = rect.top;
+              height = rect.bottom - rect.top;
+
+              if (!GetClientRect(w, &rect))
+                {
+                   ERR("GetClientRect() failed");
+                   break;
+                }
+
+              if (!MoveWindow(w, rect.left, y,
+                              rect.right - rect.left,
+                              height,
+                              TRUE))
+                {
+                   ERR("MoveWindow() failed");
+                }
+           }
+         break;
+      case ECORE_WIN32_WINDOW_STATE_MAXIMIZED_HORZ:
+         if (ew->state.maximized_horz)
+           {
+              RECT rect;
+
+              if (!GetClientRect(w, &rect))
+                {
+                   ERR("GetClientRect() failed");
+                   break;
+                }
+
+              if (!MoveWindow(w, 0, rect.top,
+                              GetSystemMetrics(SM_CXSCREEN),
+                              rect.bottom - rect.top,
+                              TRUE))
+                {
+                   ERR("MoveWindow() failed");
+                }
+           }
+         break;
+      case ECORE_WIN32_WINDOW_STATE_MAXIMIZED:
+         if (ew->state.maximized_vert && ew->state.maximized_horz)
+           {
+              RECT rect;
+
+              if (!SystemParametersInfo(SPI_GETWORKAREA, 0,
+                                        &rect, 0))
+                {
+                   ERR("SystemParametersInfo() failed");
+                   break;
+                }
+
+              if (!MoveWindow(w, 0, 0,
+                              GetSystemMetrics(SM_CXSCREEN),
+                              rect.bottom - rect.top,
+                              TRUE))
+                {
+                   ERR("MoveWindow() failed");
+                }
+           }
+         break;
+      case ECORE_WIN32_WINDOW_STATE_SHADED:
+         ew->state.shaded = 1;
+         break;
+      case ECORE_WIN32_WINDOW_STATE_HIDDEN:
+         ew->state.hidden = 1;
+         break;
+      case ECORE_WIN32_WINDOW_STATE_FULLSCREEN:
+         if (ew->state.fullscreen)
+           ecore_win32_window_fullscreen_set(window, set);
+         break;
+      case ECORE_WIN32_WINDOW_STATE_ABOVE:
+         if (ew->state.above)
+           if (!SetWindowPos(w, HWND_TOP,
+                             0, 0,
+                             0, 0,
+                             SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW))
+             {
+                ERR("SetWindowPos() failed");
+             }
+         break;
+      case ECORE_WIN32_WINDOW_STATE_BELOW:
+         if (ew->state.below)
+           if (!SetWindowPos(w, HWND_BOTTOM,
+                             0, 0,
+                             0, 0,
+                             SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW))
+             {
+                ERR("SetWindowPos() failed");
+             }
+         break;
+      case ECORE_WIN32_WINDOW_STATE_DEMANDS_ATTENTION:
+         ew->state.demands_attention = 1;
+         break;
+      case ECORE_WIN32_WINDOW_STATE_UNKNOWN:
+         /* nothing to be done */
+         break;
+     }
+}
+
+void
+ecore_win32_window_type_set(Ecore_Win32_Window      *window,
+                            Ecore_Win32_Window_Type  type)
+{
+   if (!window)
+     return;
+
+   INF("setting window type");
+
+   switch (type)
+     {
+     case ECORE_WIN32_WINDOW_TYPE_DESKTOP:
+       ((struct _Ecore_Win32_Window *)window)->type.desktop = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_DOCK:
+       ((struct _Ecore_Win32_Window *)window)->type.dock = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_TOOLBAR:
+       ((struct _Ecore_Win32_Window *)window)->type.toolbar = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_MENU:
+       ((struct _Ecore_Win32_Window *)window)->type.menu = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_UTILITY:
+       ((struct _Ecore_Win32_Window *)window)->type.utility = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_SPLASH:
+       ((struct _Ecore_Win32_Window *)window)->type.splash = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_DIALOG:
+       ((struct _Ecore_Win32_Window *)window)->type.dialog = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_NORMAL:
+       ((struct _Ecore_Win32_Window *)window)->type.normal = 1;
+       break;
+     case ECORE_WIN32_WINDOW_TYPE_UNKNOWN:
+       ((struct _Ecore_Win32_Window *)window)->type.normal = 1;
+       break;
+     }
+}
+
+
+/***** Private functions definitions *****/
+
+static Ecore_Win32_Window *
+ecore_win32_window_internal_new(Ecore_Win32_Window *parent,
+                                int                 x,
+                                int                 y,
+                                int                 width,
+                                int                 height,
+                                DWORD               style)
+{
+   RECT                        rect;
+   struct _Ecore_Win32_Window *w;
+   int                         minimal_width;
+   int                         minimal_height;
+
+   w = (struct _Ecore_Win32_Window *)calloc(1, sizeof(struct _Ecore_Win32_Window));
+   if (!w)
+     {
+        ERR("malloc() failed");
+        return NULL;
+     }
+
+   rect.left = 0;
+   rect.top = 0;
+   rect.right = width;
+   rect.bottom = height;
+   if (!AdjustWindowRect(&rect, style, FALSE))
+     {
+        ERR("AdjustWindowRect() failed");
+        free(w);
+        return NULL;
+     }
+
+   minimal_width = GetSystemMetrics(SM_CXMIN);
+   minimal_height = GetSystemMetrics(SM_CYMIN);
+/*    if (((rect.right - rect.left) < minimal_width) || */
+/*        ((rect.bottom - rect.top) < minimal_height)) */
+/*      { */
+/*         fprintf (stderr, "[Ecore] [Win32] ERROR !!\n"); */
+/*         fprintf (stderr, "                Wrong size %ld\n", rect.right - rect.left); */
+/*         free(w); */
+/*         return NULL; */
+/*      } */
+   if ((rect.right - rect.left) < minimal_width)
+     {
+       rect.right = rect.left + minimal_width;
+     }
+
+   w->window = CreateWindowEx(0,
+                              ECORE_WIN32_WINDOW_CLASS, "",
+                              style,
+                              x, y,
+                              rect.right - rect.left,
+                              rect.bottom - rect.top,
+                              parent ? ((struct _Ecore_Win32_Window *)parent)->window : NULL,
+                              NULL, _ecore_win32_instance, NULL);
+   if (!w->window)
+     {
+        ERR("CreateWindowEx() failed");
+        free(w);
+        return NULL;
+     }
+
+   SetLastError(0);
+   if (!SetWindowLongPtr(w->window, GWL_USERDATA, (LONG)w) && (GetLastError() != 0))
+     {
+        ERR("SetWindowLongPtr() failed");
+        DestroyWindow(w->window);
+        free(w);
+        return NULL;
+     }
+
+   w->min_width   = 0;
+   w->min_height  = 0;
+   w->max_width   = 32767;
+   w->max_height  = 32767;
+   w->base_width  = -1;
+   w->base_height = -1;
+   w->step_width  = -1;
+   w->step_height = -1;
+
+   w->state.iconified         = 0;
+   w->state.modal             = 0;
+   w->state.sticky            = 0;
+   w->state.maximized_vert    = 0;
+   w->state.maximized_horz    = 0;
+   w->state.shaded            = 0;
+   w->state.hidden            = 0;
+   w->state.fullscreen        = 0;
+   w->state.above             = 0;
+   w->state.below             = 0;
+   w->state.demands_attention = 0;
+
+   w->type.desktop = 0;
+   w->type.dock    = 0;
+   w->type.toolbar = 0;
+   w->type.menu    = 0;
+   w->type.utility = 0;
+   w->type.splash  = 0;
+   w->type.dialog  = 0;
+   w->type.normal  = 0;
+
+   w->pointer_is_in = 0;
+   w->borderless    = 0;
+   w->iconified     = 0;
+   w->fullscreen    = 0;
+
+   return w;
+}
diff --git a/src/lib/ecore_wince/.cvsignore b/src/lib/ecore_wince/.cvsignore
new file mode 100644 (file)
index 0000000..584f554
--- /dev/null
@@ -0,0 +1,4 @@
+.libs
+.deps
+Makefile
+Makefile.in
diff --git a/src/lib/ecore_wince/Ecore_WinCE.h b/src/lib/ecore_wince/Ecore_WinCE.h
new file mode 100644 (file)
index 0000000..30fe6b0
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef __ECORE_WINCE_H__
+#define __ECORE_WINCE_H__
+
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WINCE
+# ifdef EFL_ECORE_WINCE_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_WINCE_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WINCE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef _ECORE_EVAS_H
+typedef void Ecore_WinCE_Window;
+#endif
+
+
+/* Events */
+
+typedef struct _Ecore_WinCE_Event_Mouse_In              Ecore_WinCE_Event_Mouse_In;
+typedef struct _Ecore_WinCE_Event_Mouse_Out             Ecore_WinCE_Event_Mouse_Out;
+typedef struct _Ecore_WinCE_Event_Window_Focus_In       Ecore_WinCE_Event_Window_Focus_In;
+typedef struct _Ecore_WinCE_Event_Window_Focus_Out      Ecore_WinCE_Event_Window_Focus_Out;
+typedef struct _Ecore_WinCE_Event_Window_Damage         Ecore_WinCE_Event_Window_Damage;
+typedef struct _Ecore_WinCE_Event_Window_Create         Ecore_WinCE_Event_Window_Create;
+typedef struct _Ecore_WinCE_Event_Window_Destroy        Ecore_WinCE_Event_Window_Destroy;
+typedef struct _Ecore_WinCE_Event_Window_Hide           Ecore_WinCE_Event_Window_Hide;
+typedef struct _Ecore_WinCE_Event_Window_Show           Ecore_WinCE_Event_Window_Show;
+typedef struct _Ecore_WinCE_Event_Window_Delete_Request Ecore_WinCE_Event_Window_Delete_Request;
+
+struct _Ecore_WinCE_Event_Mouse_In
+{
+   Ecore_WinCE_Window *window;
+   int                 x;
+   int                 y;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Mouse_Out
+{
+   Ecore_WinCE_Window *window;
+   int                 x;
+   int                 y;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Focus_In
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Focus_Out
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Damage
+{
+   Ecore_WinCE_Window *window;
+   int                 x;
+   int                 y;
+   int                 width;
+   int                 height;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Create
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Destroy
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Hide
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Show
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+struct _Ecore_WinCE_Event_Window_Delete_Request
+{
+   Ecore_WinCE_Window *window;
+   long                time;
+};
+
+
+EAPI extern int ECORE_WINCE_EVENT_MOUSE_IN;
+EAPI extern int ECORE_WINCE_EVENT_MOUSE_OUT;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_FOCUS_IN;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_FOCUS_OUT;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_DAMAGE;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_CREATE;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_DESTROY;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_HIDE;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_SHOW;
+EAPI extern int ECORE_WINCE_EVENT_WINDOW_DELETE_REQUEST;
+
+
+/* Core */
+
+EAPI int    ecore_wince_init();
+EAPI int    ecore_wince_shutdown();
+EAPI long   ecore_wince_current_time_get(void);
+EAPI void   ecore_wince_message_loop_begin (void);
+
+/* Window */
+
+EAPI Ecore_WinCE_Window *ecore_wince_window_new(Ecore_WinCE_Window *parent,
+                                                int                 x,
+                                                int                 y,
+                                                int                 width,
+                                                int                 height);
+
+EAPI void ecore_wince_window_free(Ecore_WinCE_Window *window);
+
+EAPI void *ecore_wince_window_hwnd_get(Ecore_WinCE_Window *window);
+
+EAPI void ecore_wince_window_move(Ecore_WinCE_Window *window,
+                                  int                 x,
+                                  int                 y);
+
+EAPI void ecore_wince_window_resize(Ecore_WinCE_Window *window,
+                                    int                 width,
+                                    int                 height);
+
+EAPI void ecore_wince_window_move_resize(Ecore_WinCE_Window *window,
+                                         int                 x,
+                                         int                 y,
+                                         int                 width,
+                                         int                 height);
+
+EAPI void ecore_wince_window_show(Ecore_WinCE_Window *window);
+
+EAPI void ecore_wince_window_hide(Ecore_WinCE_Window *window);
+
+EAPI void ecore_wince_window_title_set(Ecore_WinCE_Window *window,
+                                       const char         *title);
+
+EAPI void ecore_wince_window_backend_set(Ecore_WinCE_Window *window, int backend);
+
+EAPI void ecore_wince_window_suspend_set(Ecore_WinCE_Window *window, int (*suspend)(int));
+
+EAPI void ecore_wince_window_resume_set(Ecore_WinCE_Window *window, int (*resume)(int));
+
+EAPI void ecore_wince_window_geometry_get(Ecore_WinCE_Window *window,
+                                          int                *x,
+                                          int                *y,
+                                          int                *width,
+                                          int                *height);
+
+EAPI void ecore_wince_window_size_get(Ecore_WinCE_Window *window,
+                                      int                *width,
+                                      int                *height);
+
+EAPI void ecore_wince_window_fullscreen_set(Ecore_WinCE_Window *window,
+                                            int                 on);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ECORE_WINCE_H__ */
diff --git a/src/lib/ecore_wince/Makefile.am b/src/lib/ecore_wince/Makefile.am
new file mode 100644 (file)
index 0000000..2ea84f6
--- /dev/null
@@ -0,0 +1,40 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_input \
+@EFL_ECORE_WINCE_BUILD@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+AM_CFLAGS = @WIN32_CFLAGS@
+
+
+if BUILD_ECORE_WINCE
+
+lib_LTLIBRARIES = libecore_wince.la
+
+include_HEADERS = \
+Ecore_WinCE.h
+
+libecore_wince_la_SOURCES = \
+ecore_wince.c \
+ecore_wince_event.c \
+ecore_wince_window.c
+
+libecore_wince_la_LIBADD = \
+@WIN32_LIBS@ \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+$(top_builddir)/src/lib/ecore/libecore.la \
+@EVAS_LIBS@ \
+@EINA_LIBS@ \
+@EVIL_LIBS@
+
+libecore_wince_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @ecore_wince_release_info@
+
+endif
+
+EXTRA_DIST = ecore_wince_private.h
diff --git a/src/lib/ecore_wince/ecore_wince.c b/src/lib/ecore_wince/ecore_wince.c
new file mode 100644 (file)
index 0000000..c507471
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>   /* for printf */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "Ecore_WinCE.h"
+#include "ecore_wince_private.h"
+
+
+/***** Global declarations *****/
+
+double              _ecore_wince_double_click_time = 0.25;
+long                _ecore_wince_event_last_time = 0;
+Ecore_WinCE_Window *_ecore_wince_event_last_window = NULL;
+HINSTANCE           _ecore_wince_instance = NULL;
+int                 _ecore_wince_log_dom_global = -1;
+
+int ECORE_WINCE_EVENT_MOUSE_IN              = 0;
+int ECORE_WINCE_EVENT_MOUSE_OUT             = 0;
+int ECORE_WINCE_EVENT_WINDOW_FOCUS_IN       = 0;
+int ECORE_WINCE_EVENT_WINDOW_FOCUS_OUT      = 0;
+int ECORE_WINCE_EVENT_WINDOW_DAMAGE         = 0;
+int ECORE_WINCE_EVENT_WINDOW_CREATE         = 0;
+int ECORE_WINCE_EVENT_WINDOW_DESTROY        = 0;
+int ECORE_WINCE_EVENT_WINDOW_SHOW           = 0;
+int ECORE_WINCE_EVENT_WINDOW_HIDE           = 0;
+int ECORE_WINCE_EVENT_WINDOW_DELETE_REQUEST = 0;
+
+
+/***** Private declarations *****/
+
+static int       _ecore_wince_init_count = 0;
+
+LRESULT CALLBACK _ecore_wince_window_procedure(HWND   window,
+                                               UINT   message,
+                                               WPARAM window_param,
+                                               LPARAM data_param);
+
+static void      _ecore_wince_error_print_cb(const Eina_Log_Domain *d,
+                                             Eina_Log_Level   level,
+                                             const char      *file,
+                                             const char      *fnc,
+                                             int              line,
+                                             const char      *fmt,
+                                             void            *data,
+                                             va_list          args);
+
+
+/***** API *****/
+
+int
+ecore_wince_init()
+{
+   WNDCLASS wc;
+
+   if (++_ecore_wince_init_count != 1)
+     return _ecore_wince_init_count;
+
+   if (!eina_init())
+     return --_ecore_wince_init_count;
+
+   eina_log_print_cb_set(_ecore_wince_error_print_cb, NULL);
+   _ecore_wince_log_dom_global = eina_log_domain_register("ecore_wince", ECORE_WINCE_DEFAULT_LOG_COLOR);
+   if (_ecore_wince_log_dom_global < 0)
+     {
+        EINA_LOG_ERR("Ecore_WinCE: Could not register log domain");
+        goto shutdown_eina;
+      }
+
+   if (!ecore_event_init())
+     {
+        ERR("Ecore_WinCE: Could not init ecore_event");
+        goto unregister_log_domain;
+     }
+
+   _ecore_wince_instance = GetModuleHandle(NULL);
+   if (!_ecore_wince_instance)
+     {
+        ERR("GetModuleHandle() failed");
+        goto shutdown_ecore_event;
+     }
+
+   memset (&wc, 0, sizeof (wc));
+   wc.style = CS_HREDRAW | CS_VREDRAW;
+   wc.lpfnWndProc = _ecore_wince_window_procedure;
+   wc.cbClsExtra = 0;
+   wc.cbWndExtra = 0;
+   wc.hInstance = _ecore_wince_instance;
+   wc.hIcon = NULL;
+   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+   wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
+   wc.lpszMenuName =  NULL;
+   wc.lpszClassName = ECORE_WINCE_WINDOW_CLASS;
+
+   if(!RegisterClass(&wc))
+     {
+        ERR("RegisterClass() failed");
+        goto free_library;
+     }
+
+   if (!ECORE_WINCE_EVENT_MOUSE_IN)
+     {
+        ECORE_WINCE_EVENT_MOUSE_IN              = ecore_event_type_new();
+        ECORE_WINCE_EVENT_MOUSE_OUT             = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_FOCUS_IN       = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_FOCUS_OUT      = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_DAMAGE         = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_CREATE         = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_DESTROY        = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_SHOW           = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_HIDE           = ecore_event_type_new();
+        ECORE_WINCE_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
+     }
+
+   return _ecore_wince_init_count;
+
+ free_library:
+   FreeLibrary(_ecore_wince_instance);
+ shutdown_ecore_event:
+   ecore_event_shutdown();
+ unregister_log_domain:
+   eina_log_domain_unregister(_ecore_wince_log_dom_global);
+ shutdown_eina:
+   eina_shutdown();
+
+   return --_ecore_wince_init_count;
+}
+
+int
+ecore_wince_shutdown()
+{
+   HWND task_bar;
+
+   if (--_ecore_wince_init_count != 0)
+     return _ecore_wince_init_count;
+
+   /* force task bar to be shown (in case the application exits */
+   /* while being fullscreen) */
+   task_bar = FindWindow(L"HHTaskBar", NULL);
+   if (task_bar)
+     {
+        ShowWindow(task_bar, SW_SHOW);
+        EnableWindow(task_bar, TRUE);
+     }
+
+   if (!UnregisterClass(ECORE_WINCE_WINDOW_CLASS, _ecore_wince_instance))
+     ERR("UnregisterClass() failed");
+
+   if (!FreeLibrary(_ecore_wince_instance))
+     ERR("FreeLibrary() failed");
+
+   _ecore_wince_instance = NULL;
+
+   ecore_event_shutdown();
+   eina_log_domain_unregister(_ecore_wince_log_dom_global);
+   _ecore_wince_log_dom_global = -1;
+   eina_shutdown();
+
+   return _ecore_wince_init_count;
+}
+
+/**
+ * Sets the timeout for a double and triple clicks to be flagged.
+ *
+ * This sets the time between clicks before the double_click flag is
+ * set in a button down event. If 3 clicks occur within double this
+ * time, the triple_click flag is also set.
+ *
+ * @param t The time in seconds
+ */
+EAPI void
+ecore_wince_double_click_time_set(double t)
+{
+   if (t < 0.0) t = 0.0;
+   _ecore_wince_double_click_time = t;
+}
+
+/**
+ * Retrieves the double and triple click flag timeout.
+ *
+ * See @ref ecore_wince_double_click_time_set for more information.
+ *
+ * @return The timeout for double clicks in seconds.
+ */
+EAPI double
+ecore_wince_double_click_time_get(void)
+{
+   return _ecore_wince_double_click_time;
+}
+
+/**
+ * Return the last event time
+ */
+EAPI long
+ecore_wince_current_time_get(void)
+{
+   return _ecore_wince_event_last_time;
+}
+
+
+/***** Private functions definitions *****/
+
+LRESULT CALLBACK
+_ecore_wince_window_procedure(HWND   window,
+                              UINT   message,
+                              WPARAM window_param,
+                              LPARAM data_param)
+{
+   Ecore_WinCE_Callback_Data *data;
+   POINTS                     pt;
+   DWORD                      coord;
+
+   data = (Ecore_WinCE_Callback_Data *)malloc(sizeof(Ecore_WinCE_Callback_Data));
+   if (!data) return DefWindowProc(window, message, window_param, data_param);
+
+   data->window = window;
+   data->message = message;
+   data->window_param = window_param;
+   data->data_param = data_param;
+   data->time = GetTickCount();
+   coord = GetMessagePos();
+   pt = MAKEPOINTS(coord);
+   data->x = pt.x;
+   data->y = pt.y;
+
+   switch (data->message)
+     {
+       /* Keyboard input notifications */
+     case WM_CHAR:
+       _ecore_wince_event_handle_key_press(data, 0);
+       break;
+     case WM_HOTKEY:
+       _ecore_wince_event_handle_key_press(data, 1);
+       break;
+     case WM_KEYDOWN:
+     case WM_SYSKEYDOWN:
+       _ecore_wince_event_handle_key_press(data, 1);
+       break;
+     case WM_KEYUP:
+     case WM_SYSKEYUP:
+       _ecore_wince_event_handle_key_release(data, 1);
+       break;
+     case WM_SETFOCUS:
+       _ecore_wince_event_handle_focus_in(data);
+       break;
+     case WM_KILLFOCUS:
+       _ecore_wince_event_handle_focus_out(data);
+       break;
+       /* Mouse input notifications */
+     case WM_LBUTTONDOWN:
+       _ecore_wince_event_handle_button_press(data, 1);
+       break;
+     case WM_LBUTTONUP:
+       _ecore_wince_event_handle_button_release(data, 1);
+       break;
+     case WM_MOUSEMOVE:
+       {
+          RECT                        rect;
+          struct _Ecore_WinCE_Window *w = NULL;
+
+          w = (struct _Ecore_WinCE_Window *)GetWindowLong(window, GWL_USERDATA);
+
+          if (GetClientRect(window, &rect))
+            {
+               POINT pt;
+
+               INF("mouse in window");
+
+               pt.x = LOWORD(data_param);
+               pt.y = HIWORD(data_param);
+               if (!PtInRect(&rect, pt))
+                 {
+                    if (w->pointer_is_in)
+                      {
+                         w->pointer_is_in = 0;
+                         _ecore_wince_event_handle_leave_notify(data);
+                      }
+                 }
+               else
+                 {
+                    if (!w->pointer_is_in)
+                      {
+                         w->pointer_is_in = 1;
+                         _ecore_wince_event_handle_enter_notify(data);
+                      }
+                 }
+            }
+          else
+            {
+               ERR("GetClientRect() failed");
+            }
+          _ecore_wince_event_handle_motion_notify(data);
+
+          break;
+       }
+       /* Window notifications */
+     case WM_CREATE:
+       _ecore_wince_event_handle_create_notify(data);
+       break;
+     case WM_DESTROY:
+       _ecore_wince_event_handle_destroy_notify(data);
+       break;
+     case WM_SHOWWINDOW:
+       if ((data->data_param == SW_OTHERUNZOOM) ||
+           (data->data_param == SW_OTHERUNZOOM))
+         break;
+
+       if (data->window_param)
+         _ecore_wince_event_handle_map_notify(data);
+       else
+         _ecore_wince_event_handle_unmap_notify(data);
+
+       break;
+     case WM_CLOSE:
+       _ecore_wince_event_handle_delete_request(data);
+       break;
+       /* GDI notifications */
+     case WM_PAINT:
+       {
+          PAINTSTRUCT paint;
+
+          if (BeginPaint(window, &paint))
+            {
+               data->update = paint.rcPaint;
+               _ecore_wince_event_handle_expose(data);
+               EndPaint(window, &paint);
+            }
+          break;
+       }
+     default:
+       return DefWindowProc(window, message, window_param, data_param);
+     }
+
+   return 0;
+}
+
+static void
+_ecore_wince_error_print_cb(const Eina_Log_Domain *d __UNUSED__,
+                            Eina_Log_Level  level __UNUSED__,
+                            const char     *file __UNUSED__,
+                            const char     *fnc,
+                            int             line,
+                            const char     *fmt,
+                            void           *data __UNUSED__,
+                            va_list         args)
+{
+   fprintf(stderr, "[%s:%d] ", fnc, line);
+   vfprintf(stderr, fmt, args);
+}
diff --git a/src/lib/ecore_wince/ecore_wince_event.c b/src/lib/ecore_wince/ecore_wince_event.c
new file mode 100644 (file)
index 0000000..f61f5f9
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "Ecore_WinCE.h"
+#include "ecore_wince_private.h"
+
+
+/***** Private declarations *****/
+
+static Ecore_WinCE_Window *_ecore_wince_mouse_down_last_window = NULL;
+static Ecore_WinCE_Window *_ecore_wince_mouse_down_last_last_window = NULL;
+static long                _ecore_wince_mouse_down_last_time = 0;
+static long                _ecore_wince_mouse_down_last_last_time = 0;
+static int                 _ecore_wince_mouse_down_did_triple = 0;
+static int                 _ecore_wince_mouse_up_count = 0;
+
+
+static void _ecore_wince_event_free_key_down(void *data,
+                                             void *ev);
+
+static void _ecore_wince_event_free_key_up(void *data,
+                                           void *ev);
+
+static int  _ecore_wince_event_keystroke_get(int    key,
+                                             char **keyname,
+                                             char **keysymbol,
+                                             char **keycompose);
+
+static int  _ecore_wince_event_char_get(int    key,
+                                        char **keyname,
+                                        char **keysymbol,
+                                        char **keycompose);
+
+
+/***** Global functions *****/
+
+void
+_ecore_wince_event_handle_key_press(Ecore_WinCE_Callback_Data *msg,
+                                    int                        is_keystroke)
+{
+   Ecore_Event_Key *e;
+
+   INF("key pressed");
+
+   e = (Ecore_Event_Key *)malloc(sizeof(Ecore_Event_Key));
+   if (!e) return;
+
+   if (is_keystroke)
+     {
+        if (!_ecore_wince_event_keystroke_get(LOWORD(msg->window_param),
+                                              (char **)&e->keyname,
+                                              (char **)&e->key,
+                                              (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+   else
+     {
+        if (!_ecore_wince_event_char_get(LOWORD(msg->window_param),
+                                         (char **)&e->keyname,
+                                         (char **)&e->key,
+                                         (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+   e->timestamp = msg->time;
+
+   _ecore_wince_event_last_time = e->timestamp;
+
+   ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_wince_event_free_key_down, NULL);
+}
+
+void
+_ecore_wince_event_handle_key_release(Ecore_WinCE_Callback_Data *msg,
+                                      int                        is_keystroke)
+{
+   Ecore_Event_Key *e;
+
+   INF("key released");
+
+   e = (Ecore_Event_Key *)calloc(1, sizeof(Ecore_Event_Key));
+   if (!e) return;
+
+   if (is_keystroke)
+     {
+        if (!_ecore_wince_event_keystroke_get(LOWORD(msg->window_param),
+                                              (char **)&e->keyname,
+                                              (char **)&e->key,
+                                              (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+   else
+     {
+        if (!_ecore_wince_event_char_get(LOWORD(msg->window_param),
+                                         (char **)&e->keyname,
+                                         (char **)&e->key,
+                                         (char **)&e->string))
+          {
+             free(e);
+             return;
+          }
+     }
+
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+   e->timestamp = msg->time;
+
+   _ecore_wince_event_last_time = e->timestamp;
+
+   ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_wince_event_free_key_up, NULL);
+}
+
+void
+_ecore_wince_event_handle_button_press(Ecore_WinCE_Callback_Data *msg,
+                                       int                        button)
+{
+   Ecore_WinCE_Window *window;
+
+   INF("mouse button pressed");
+
+   window = (Ecore_WinCE_Window *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   {
+      Ecore_Event_Mouse_Move *e;
+
+      e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->x = LOWORD(msg->data_param);
+      e->y = HIWORD(msg->data_param);
+      e->timestamp = msg->time;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+   }
+
+   {
+      Ecore_Event_Mouse_Button *e;
+
+      if (_ecore_wince_mouse_down_did_triple)
+        {
+           _ecore_wince_mouse_down_last_window = NULL;
+           _ecore_wince_mouse_down_last_last_window = NULL;
+           _ecore_wince_mouse_down_last_time = 0;
+           _ecore_wince_mouse_down_last_last_time = 0;
+        }
+
+      e = (Ecore_Event_Mouse_Button *)calloc(1, sizeof(Ecore_Event_Mouse_Button));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->buttons = button;
+      e->x = LOWORD(msg->data_param);
+      e->y = HIWORD(msg->data_param);
+      e->timestamp = msg->time;
+
+      if (((e->timestamp - _ecore_wince_mouse_down_last_time) <= (long)(1000 * _ecore_wince_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_window))
+        e->double_click = 1;
+
+      if (((e->timestamp - _ecore_wince_mouse_down_last_last_time) <= (long)(2 * 1000 * _ecore_wince_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_window) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_last_window))
+        {
+           e->triple_click = 1;
+           _ecore_wince_mouse_down_did_triple = 1;
+        }
+      else
+        _ecore_wince_mouse_down_did_triple = 0;
+
+      if (!e->double_click && !e->triple_click)
+        _ecore_wince_mouse_up_count = 0;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      if (!_ecore_wince_mouse_down_did_triple)
+        {
+           _ecore_wince_mouse_down_last_last_window = _ecore_wince_mouse_down_last_window;
+           _ecore_wince_mouse_down_last_window = (Ecore_WinCE_Window *)e->window;
+           _ecore_wince_mouse_down_last_last_time = _ecore_wince_mouse_down_last_time;
+           _ecore_wince_mouse_down_last_time = e->timestamp;
+        }
+
+      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_wince_event_handle_button_release(Ecore_WinCE_Callback_Data *msg,
+                                         int                        button)
+{
+   Ecore_WinCE_Window *window;
+
+   INF("mouse button released");
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   {
+      Ecore_Event_Mouse_Move *e;
+
+      e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->x = LOWORD(msg->data_param);
+      e->y = HIWORD(msg->data_param);
+      e->timestamp = msg->time;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+   }
+
+   {
+      Ecore_Event_Mouse_Button *e;
+
+      e = (Ecore_Event_Mouse_Button *)calloc(1, sizeof(Ecore_Event_Mouse_Button));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->buttons = button;
+      e->x = LOWORD(msg->data_param);
+      e->y = HIWORD(msg->data_param);
+      e->timestamp = msg->time;
+
+      _ecore_wince_mouse_up_count++;
+
+      if ((_ecore_wince_mouse_up_count >= 2) &&
+          ((e->timestamp - _ecore_wince_mouse_down_last_time) <= (long)(1000 * _ecore_wince_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_window))
+        e->double_click = 1;
+
+      if ((_ecore_wince_mouse_up_count >= 3) &&
+          ((e->timestamp - _ecore_wince_mouse_down_last_last_time) <= (long)(2 * 1000 * _ecore_wince_double_click_time)) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_window) &&
+          (e->window == (Ecore_Window)_ecore_wince_mouse_down_last_last_window))
+        e->triple_click = 1;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_wince_event_handle_motion_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   INF("mouse moved");
+
+   e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+   if (!e) return;
+
+   e->window = (Ecore_Window)GetWindowLong(msg->window, GWL_USERDATA);
+   e->x = LOWORD(msg->data_param);
+   e->y = HIWORD(msg->data_param);
+   e->timestamp = msg->time;
+
+   ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_enter_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Window *window;
+
+   INF("mouse in");
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   {
+      Ecore_Event_Mouse_Move *e;
+
+      e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->x = msg->x;
+      e->y = msg->y;
+      e->timestamp = msg->time;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+   }
+
+   {
+      Ecore_WinCE_Event_Mouse_In *e;
+
+      e = (Ecore_WinCE_Event_Mouse_In *)calloc(1, sizeof(Ecore_WinCE_Event_Mouse_In));
+      if (!e) return;
+
+      e->window = window;
+      e->x = msg->x;
+      e->y = msg->y;
+      e->time = msg->time;
+
+      _ecore_wince_event_last_time = e->time;
+
+      ecore_event_add(ECORE_WINCE_EVENT_MOUSE_IN, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_wince_event_handle_leave_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Window *window;
+
+   INF("mouse out");
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+
+   {
+      Ecore_Event_Mouse_Move *e;
+
+      e = (Ecore_Event_Mouse_Move *)calloc(1, sizeof(Ecore_Event_Mouse_Move));
+      if (!e) return;
+
+      e->window = (Ecore_Window)window;
+      e->x = msg->x;
+      e->y = msg->y;
+      e->timestamp = msg->time;
+
+      _ecore_wince_event_last_time = e->timestamp;
+      _ecore_wince_event_last_window = (Ecore_WinCE_Window *)e->window;
+
+      ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL);
+   }
+
+   {
+      Ecore_WinCE_Event_Mouse_Out *e;
+
+      e = (Ecore_WinCE_Event_Mouse_Out *)calloc(1, sizeof(Ecore_WinCE_Event_Mouse_Out));
+      if (!e) return;
+
+      e->window = window;
+      e->x = msg->x;
+      e->y = msg->y;
+      e->time = msg->time;
+
+      _ecore_wince_event_last_time = e->time;
+
+      ecore_event_add(ECORE_WINCE_EVENT_MOUSE_OUT, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_wince_event_handle_focus_in(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Focus_In *e;
+   struct _Ecore_WinCE_Window        *window;
+
+   INF("focus in");
+
+   e = (Ecore_WinCE_Event_Window_Focus_In *)calloc(1, sizeof(Ecore_WinCE_Event_Window_Focus_In));
+   if (!e) return;
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   if (window->resume)
+     window->resume(window->backend);
+
+   e->window = window;
+
+   e->time = _ecore_wince_event_last_time;
+   _ecore_wince_event_last_time = e->time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_focus_out(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Focus_Out *e;
+   struct _Ecore_WinCE_Window         *window;
+
+   INF("focus out");
+
+   e = (Ecore_WinCE_Event_Window_Focus_Out *)calloc(1, sizeof(Ecore_WinCE_Event_Window_Focus_Out));
+   if (!e) return;
+
+   window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+   if (window->suspend)
+     window->suspend(window->backend);
+
+   e->window = window;
+
+   e->time = _ecore_wince_event_last_time;
+   _ecore_wince_event_last_time = e->time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_expose(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Damage *e;
+
+   INF("window expose");
+
+   e = (Ecore_WinCE_Event_Window_Damage *)calloc(1, sizeof(Ecore_WinCE_Event_Window_Damage));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->x = msg->update.left;
+   e->y = msg->update.top;
+   e->width = msg->update.right - msg->update.left;
+   e->height = msg->update.bottom - msg->update.top;
+   INF("window expose size: %dx%d", e->width, e->height);
+
+   e->time = _ecore_wince_event_last_time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_create_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Create *e;
+
+   INF("window create notify");
+
+   e = calloc(1, sizeof(Ecore_WinCE_Event_Window_Create));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->time = _ecore_wince_event_last_time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_CREATE, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_destroy_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Destroy *e;
+
+   INF("window destroy notify");
+
+   e = calloc(1, sizeof(Ecore_WinCE_Event_Window_Destroy));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->time = _ecore_wince_event_last_time;
+/*    if (e->window == _ecore_wince_event_last_window) _ecore_wince_event_last_window = NULL; */
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_DESTROY, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_map_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Show *e;
+
+   INF("window map notify");
+
+   e = calloc(1, sizeof(Ecore_WinCE_Event_Window_Show));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->time = _ecore_wince_event_last_time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_SHOW, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_unmap_notify(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Hide *e;
+
+   INF("window unmap notify");
+
+   e = calloc(1, sizeof(Ecore_WinCE_Event_Window_Hide));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->time = _ecore_wince_event_last_time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_HIDE, e, NULL, NULL);
+}
+
+void
+_ecore_wince_event_handle_delete_request(Ecore_WinCE_Callback_Data *msg)
+{
+   Ecore_WinCE_Event_Window_Delete_Request *e;
+
+   INF("window delete request");
+
+   e = calloc(1, sizeof(Ecore_WinCE_Event_Window_Delete_Request));
+   if (!e) return;
+
+   e->window = (void *)GetWindowLong(msg->window, GWL_USERDATA);
+   if (!e->window)
+     {
+        free(e);
+        return;
+     }
+
+   e->time = _ecore_wince_event_last_time;
+
+   ecore_event_add(ECORE_WINCE_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
+}
+
+
+/***** Private functions definitions *****/
+
+static void
+_ecore_wince_event_free_key_down(void *data __UNUSED__,
+                                 void *ev)
+{
+   Ecore_Event_Key *e;
+
+   e = ev;
+   if (e->keyname) free((char *)e->keyname);
+   if (e->key) free((char *)e->key);
+   if (e->string) free((char *)e->string);
+   free(e);
+}
+
+static void
+_ecore_wince_event_free_key_up(void *data __UNUSED__,
+                               void *ev)
+{
+   Ecore_Event_Key *e;
+
+   e = ev;
+   if (e->keyname) free((char *)e->keyname);
+   if (e->key) free((char *)e->key);
+   if (e->string) free((char *)e->string);
+   free(e);
+}
+
+static int
+_ecore_wince_event_keystroke_get(int    key,
+                                 char **keyname,
+                                 char **keysymbol,
+                                 char **keycompose)
+{
+  char *kn;
+  char *ks;
+  char *kc;
+
+  *keyname = NULL;
+  *keysymbol = NULL;
+  *keycompose = NULL;
+
+   switch (key)
+     {
+       /* Keystroke */
+     case VK_PRIOR:
+       kn = "Prior";
+       ks = "Prior";
+       kc = "Prior";
+       break;
+     case VK_NEXT:
+       kn = "Next";
+       ks = "Next";
+       kc = "Next";
+       break;
+     case VK_END:
+       kn = "End";
+       ks = "End";
+       kc = "End";
+       break;
+     case VK_HOME:
+       kn = "Home";
+       ks = "Home";
+       kc = "Home";
+       break;
+     case VK_LEFT:
+       kn = "Left";
+       ks = "Left";
+       kc = "Left";
+       break;
+     case VK_UP:
+       kn = "Up";
+       ks = "Up";
+       kc = "Up";
+       break;
+     case VK_RIGHT:
+       kn = "Right";
+       ks = "Right";
+       kc = "Right";
+       break;
+     case VK_DOWN:
+       kn = "Down";
+       ks = "Down";
+       kc = "Down";
+       break;
+     case VK_INSERT:
+       kn = "Insert";
+       ks = "Insert";
+       kc = "Insert";
+       break;
+     case VK_DELETE:
+       kn = "Delete";
+       ks = "Delete";
+       kc = "Delete";
+       break;
+     case VK_F1:
+       kn = "F1";
+       ks = "F1";
+       kc = "";
+       break;
+     case VK_F2:
+       kn = "F2";
+       ks = "F2";
+       kc = "";
+       break;
+     case VK_F3:
+       kn = "F3";
+       ks = "F3";
+       kc = "";
+       break;
+     case VK_F4:
+       kn = "F4";
+       ks = "F4";
+       kc = "";
+       break;
+     case VK_F5:
+       kn = "F5";
+       ks = "F5";
+       kc = "";
+       break;
+     case VK_F6:
+       kn = "F6";
+       ks = "F6";
+       kc = "";
+       break;
+     case VK_F7:
+       kn = "F7";
+       ks = "F7";
+       kc = "";
+       break;
+     case VK_F8:
+       kn = "F8";
+       ks = "F8";
+       kc = "";
+       break;
+     case VK_F9:
+       kn = "F9";
+       ks = "F9";
+       kc = "";
+       break;
+     case VK_F10:
+       kn = "F10";
+       ks = "F10";
+       kc = "";
+       break;
+     case VK_F11:
+       kn = "F11";
+       ks = "F11";
+       kc = "";
+       break;
+     case VK_F12:
+       kn = "F12";
+       ks = "F12";
+       kc = "";
+       break;
+     case VK_F13:
+       kn = "F13";
+       ks = "F13";
+       kc = "";
+       break;
+     case VK_F14:
+       kn = "F14";
+       ks = "F14";
+       kc = "";
+       break;
+     case VK_F15:
+       kn = "F15";
+       ks = "F15";
+       kc = "";
+       break;
+     case VK_F16:
+       kn = "F16";
+       ks = "F16";
+       kc = "";
+       break;
+     case VK_F17:
+       kn = "F17";
+       ks = "F17";
+       kc = "";
+       break;
+     case VK_F18:
+       kn = "F18";
+       ks = "F18";
+       kc = "";
+       break;
+     case VK_F19:
+       kn = "F19";
+       ks = "F19";
+       kc = "";
+       break;
+     case VK_F20:
+       /*
+       * VK_F20 indicates that an arrow key came from a rocker.
+       * This can safely be ignored.
+       */
+       return 0;
+     case VK_F21:
+       /*
+       * VK_F21 indicates that an arrow key came from a directional
+       * pad. This can safely be ignored.
+       */
+       return 0;
+     case VK_F22:
+       kn = "F22";
+       ks = "F22";
+       kc = "";
+       break;
+     case VK_F23:
+       /*
+       * Sent with VK_RETURN when doing an action (usually the middle
+       * button on a directional pad. This can safely be ignored.
+       */
+       return 0;
+     case VK_F24:
+       kn = "F24";
+       ks = "F24";
+       kc = "";
+       break;
+     case VK_APPS:
+       kn = "Application";
+       ks = "Application";
+       kc = "";
+       break;
+     case VK_MENU:
+       kn = "Menu";
+       ks = "Menu";
+       kc = "";
+       break;
+     default:
+       /* other non keystroke characters */
+       return 0;
+     }
+   *keyname = strdup(kn);
+   if (!*keyname) return 0;
+   *keysymbol = strdup(ks);
+   if (!*keysymbol)
+     {
+        free(*keyname);
+        *keyname = NULL;
+        return 0;
+     }
+   *keycompose = strdup(kc);
+   if (!*keycompose)
+     {
+        free(*keyname);
+        free(*keysymbol);
+        *keyname = NULL;
+        *keysymbol = NULL;
+        return 0;
+     }
+
+   return 1;
+}
+
+static int
+_ecore_wince_event_char_get(int    key,
+                            char **keyname,
+                            char **keysymbol,
+                            char **keycompose)
+{
+  char kn[32];
+  char ks[32];
+  char kc[32];
+
+  *keyname = NULL;
+  *keysymbol = NULL;
+  *keycompose = NULL;
+
+   switch (key)
+     {
+     case VK_APP3:
+     case VK_BACK:
+       strncpy(kn, "BackSpace", 32);
+       strncpy(ks, "BackSpace", 32);
+       strncpy(kc, "BackSpace", 32);
+       break;
+     case VK_APP4:
+     case VK_TAB:
+       strncpy(kn, "Tab", 32);
+       strncpy(ks, "Tab", 32);
+       strncpy(kc, "Tab", 32);
+       break;
+     case VK_APP5:
+     case 0x0a:
+       /* Line feed (Shift + Enter) */
+       strncpy(kn, "LineFeed", 32);
+       strncpy(ks, "LineFeed", 32);
+       strncpy(kc, "LineFeed", 32);
+       break;
+     case VK_APP2:
+     case VK_RETURN:
+       strncpy(kn, "Return", 32);
+       strncpy(ks, "Return", 32);
+       strncpy(kc, "Return", 32);
+       break;
+     case VK_APP1:
+     case VK_ESCAPE:
+       strncpy(kn, "Escape", 32);
+       strncpy(ks, "Escape", 32);
+       strncpy(kc, "Escape", 32);
+       break;
+     default:
+       /* displayable characters */
+       printf (" * key : %d\n", key);
+       kn[0] = (TCHAR)key;
+       kn[1] = '\0';
+       ks[0] = (TCHAR)key;
+       ks[1] = '\0';
+       kc[0] = (TCHAR)key;
+       kc[1] = '\0';
+       break;
+     }
+   *keyname = strdup(kn);
+   if (!*keyname) return 0;
+   *keysymbol = strdup(ks);
+   if (!*keysymbol)
+     {
+        free(*keyname);
+        *keyname = NULL;
+        return 0;
+     }
+   *keycompose = strdup(kc);
+   if (!*keycompose)
+     {
+        free(*keyname);
+        free(*keysymbol);
+        *keyname = NULL;
+        *keysymbol = NULL;
+        return 0;
+     }
+
+   return 1;
+}
diff --git a/src/lib/ecore_wince/ecore_wince_private.h b/src/lib/ecore_wince/ecore_wince_private.h
new file mode 100644 (file)
index 0000000..09a2f0d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef __ECORE_WINCE_PRIVATE_H__
+#define __ECORE_WINCE_PRIVATE_H__
+
+
+/* logging messages macros */
+extern int _ecore_wince_log_dom_global;
+
+#ifdef ECORE_WINCE_DEFAULT_LOG_COLOR
+#undef ECORE_WINCE_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_WINCE_DEFAULT_LOG_COLOR EINA_COLOR_LIGHTBLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_wince_log_dom_global , __VA_ARGS__)
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_wince_log_dom_global , __VA_ARGS__)
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_wince_log_dom_global , __VA_ARGS__)
+
+#define ECORE_WINCE_WINDOW_CLASS L"Ecore_WinCE_Window_Class"
+
+
+typedef struct _Ecore_WinCE_Callback_Data Ecore_WinCE_Callback_Data;
+
+struct _Ecore_WinCE_Callback_Data
+{
+   RECT         update;
+   HWND         window;
+   unsigned int message;
+   WPARAM       window_param;
+   LPARAM       data_param;
+   long         time;
+   int          x;
+   int          y;
+};
+
+
+typedef int (*ecore_wince_suspend) (int);
+typedef int (*ecore_wince_resume)  (int);
+
+
+struct _Ecore_WinCE_Window
+{
+   HWND                window;
+
+   int                 backend;
+   ecore_wince_suspend suspend;
+   ecore_wince_resume  resume;
+
+   RECT                rect;           /* used to go fullscreen to normal */
+
+   unsigned int        pointer_is_in : 1;
+   unsigned int        fullscreen    : 1;
+};
+
+extern HINSTANCE           _ecore_wince_instance;
+extern double              _ecore_wince_double_click_time;
+extern long                _ecore_wince_event_last_time;
+extern Ecore_WinCE_Window *_ecore_wince_event_last_window;
+
+
+void  _ecore_wince_event_handle_key_press(Ecore_WinCE_Callback_Data *msg, int is_keystroke);
+void  _ecore_wince_event_handle_key_release(Ecore_WinCE_Callback_Data *msg, int is_keystroke);
+void  _ecore_wince_event_handle_button_press(Ecore_WinCE_Callback_Data *msg, int button);
+void  _ecore_wince_event_handle_button_release(Ecore_WinCE_Callback_Data *msg, int button);
+void  _ecore_wince_event_handle_motion_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_enter_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_leave_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_focus_in(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_focus_out(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_expose(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_create_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_destroy_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_map_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_unmap_notify(Ecore_WinCE_Callback_Data *msg);
+void  _ecore_wince_event_handle_delete_request(Ecore_WinCE_Callback_Data *msg);
+
+
+#endif /* __ECORE_WINCE_PRIVATE_H__ */
diff --git a/src/lib/ecore_wince/ecore_wince_window.c b/src/lib/ecore_wince/ecore_wince_window.c
new file mode 100644 (file)
index 0000000..cf6b23f
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Evil.h>
+#include <Eina.h>
+
+#include "Ecore_WinCE.h"
+#include "ecore_wince_private.h"
+
+
+/***** Private declarations *****/
+
+typedef BOOL (__stdcall *UnregisterFunc1Proc)(UINT, UINT);
+
+static int _ecore_wince_hardware_keys_register(HWND window);
+
+
+/***** API *****/
+
+Ecore_WinCE_Window *
+ecore_wince_window_new(Ecore_WinCE_Window *parent,
+                       int                 x,
+                       int                 y,
+                       int                 width,
+                       int                 height)
+{
+   struct _Ecore_WinCE_Window *w;
+   HWND                        window;
+   RECT                        rect;
+
+   INF("creating window");
+
+   w = (struct _Ecore_WinCE_Window *)calloc(1, sizeof(struct _Ecore_WinCE_Window));
+   if (!w)
+     {
+        ERR("malloc() failed");
+        return NULL;
+     }
+
+   rect.left = 0;
+   rect.top = 0;
+   rect.right = width;
+   rect.bottom = height;
+   if (!AdjustWindowRectEx(&rect, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, FALSE, WS_EX_TOPMOST))
+     {
+        ERR("AdjustWindowRectEx() failed");
+        free(w);
+        return NULL;
+     }
+
+   window = CreateWindowEx(WS_EX_TOPMOST,
+                           ECORE_WINCE_WINDOW_CLASS,
+                           L"",
+                           WS_CAPTION | WS_SYSMENU | WS_VISIBLE,
+                           x, y,
+                           rect.right - rect.left, rect.bottom - rect.top,
+                           parent ? ((struct _Ecore_WinCE_Window *)parent)->window : NULL,
+                           NULL, _ecore_wince_instance, NULL);
+   if (!window)
+     {
+        ERR("CreateWindowEx() failed");
+        free(w);
+        return NULL;
+     }
+
+   if (!_ecore_wince_hardware_keys_register(window))
+     {
+        ERR("_ecore_wince_hardware_keys_register() failed");
+        DestroyWindow(window);
+        free(w);
+        return NULL;
+     }
+
+   w->window = window;
+
+   SetLastError(0);
+   if (!SetWindowLong(window, GWL_USERDATA, (LONG)w) && (GetLastError() != 0))
+     {
+        ERR("SetWindowLong() failed");
+        DestroyWindow(window);
+        free(w);
+        return NULL;
+     }
+
+   w->pointer_is_in = 0;
+
+   return w;
+}
+
+void
+ecore_wince_window_free(Ecore_WinCE_Window *window)
+{
+   if (!window) return;
+
+   INF("destroying window");
+
+   DestroyWindow(((struct _Ecore_WinCE_Window *)window)->window);
+   free(window);
+}
+
+void *
+ecore_wince_window_hwnd_get(Ecore_WinCE_Window *window)
+{
+   if (!window)
+     return NULL;
+
+   return ((struct _Ecore_WinCE_Window *)window)->window;
+}
+
+void
+ecore_wince_window_move(Ecore_WinCE_Window *window,
+                        int                 x,
+                        int                 y)
+{
+   RECT rect;
+   HWND w;
+
+   if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
+     return;
+
+   INF("moving window (%dx%d)", x, y);
+
+   w = ((struct _Ecore_WinCE_Window *)window)->window;
+   if (!GetWindowRect(w, &rect))
+     {
+        ERR("GetWindowRect() failed");
+        return;
+     }
+
+   if (!MoveWindow(w, x, y,
+                   rect.right - rect.left,
+                   rect.bottom - rect.top,
+                   TRUE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_wince_window_resize(Ecore_WinCE_Window *window,
+                          int                 width,
+                          int                 height)
+{
+   RECT                        rect;
+   struct _Ecore_WinCE_Window *w;
+   DWORD                       style;
+   DWORD                       exstyle;
+   int                         x;
+   int                         y;
+
+   if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
+     return;
+
+   INF("resizing window (%dx%d)", width, height);
+
+   w = (struct _Ecore_WinCE_Window *)window;
+   if (!GetWindowRect(w->window, &rect))
+     {
+        ERR("GetWindowRect() failed");
+        return;
+     }
+
+   x = rect.left;
+   y = rect.top;
+   rect.left = 0;
+   rect.top = 0;
+   rect.right = width;
+   rect.bottom = height;
+   if (!(style = GetWindowLong(w->window, GWL_STYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!(exstyle = GetWindowLong(w->window, GWL_EXSTYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!AdjustWindowRectEx(&rect, style, FALSE, exstyle))
+     {
+        ERR("AdjustWindowRectEx() failed");
+        return;
+     }
+
+   if (!MoveWindow(w->window, x, y,
+                   rect.right - rect.left,
+                   rect.bottom - rect.top,
+                   FALSE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_wince_window_move_resize(Ecore_WinCE_Window *window,
+                               int                 x,
+                               int                 y,
+                               int                 width,
+                               int                 height)
+{
+   RECT                        rect;
+   struct _Ecore_WinCE_Window *w;
+   DWORD                       style;
+   DWORD                       exstyle;
+
+   if (!window || ((struct _Ecore_WinCE_Window *)window)->fullscreen)
+     return;
+
+   INF("moving and resizing window (%dx%d %dx%d)", x, y, width, height);
+
+   w = ((struct _Ecore_WinCE_Window *)window);
+   rect.left = 0;
+   rect.top = 0;
+   rect.right = width;
+   rect.bottom = height;
+   if (!(style = GetWindowLong(w->window, GWL_STYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!(exstyle = GetWindowLong(w->window, GWL_EXSTYLE)))
+     {
+        ERR("GetWindowLong() failed");
+        return;
+     }
+   if (!AdjustWindowRectEx(&rect, style, FALSE, exstyle))
+     {
+        ERR("AdjustWindowRectEx() failed");
+        return;
+     }
+
+   if (!MoveWindow(w->window, x, y,
+              rect.right - rect.left,
+              rect.bottom - rect.top,
+              TRUE))
+     {
+        ERR("MoveWindow() failed");
+     }
+}
+
+void
+ecore_wince_window_show(Ecore_WinCE_Window *window)
+{
+   if (!window) return;
+
+   INF("showing window");
+
+   if (!ShowWindow(((struct _Ecore_WinCE_Window *)window)->window, SW_SHOWNORMAL))
+     {
+        ERR("ShowWindow() failed");
+        return;
+     }
+   if (!UpdateWindow(((struct _Ecore_WinCE_Window *)window)->window))
+     {
+        ERR("UpdateWindow() failed");
+     }
+   if (!SendMessage(((struct _Ecore_WinCE_Window *)window)->window, WM_SHOWWINDOW, 1, 0))
+     {
+        ERR("SendMessage() failed");
+     }
+}
+
+void
+ecore_wince_window_hide(Ecore_WinCE_Window *window)
+{
+   if (!window) return;
+
+   INF("hiding window");
+
+   if (!ShowWindow(((struct _Ecore_WinCE_Window *)window)->window, SW_HIDE))
+     {
+        ERR("ShowWindow() failed");
+        return;
+     }
+   if (!SendMessage(((struct _Ecore_WinCE_Window *)window)->window, WM_SHOWWINDOW, 0, 0))
+     {
+        ERR("SendMessage() failed");
+     }
+}
+
+void
+ecore_wince_window_title_set(Ecore_WinCE_Window *window,
+                             const char         *title)
+{
+   wchar_t *wtitle;
+
+   if (!window) return;
+
+   if (!title || !title[0]) return;
+
+   INF("setting window title");
+
+   wtitle = evil_char_to_wchar(title);
+   if (!wtitle) return;
+
+   if (!SetWindowText(((struct _Ecore_WinCE_Window *)window)->window, wtitle))
+     {
+        ERR("SetWindowText() failed");
+     }
+   free(wtitle);
+}
+
+void
+ecore_wince_window_backend_set(Ecore_WinCE_Window *window, int backend)
+{
+   struct _Ecore_WinCE_Window *w;
+
+   if (!window)
+     return;
+
+   INF("setting backend");
+
+   w = (struct _Ecore_WinCE_Window *)window;
+   w->backend = backend;
+}
+
+void
+ecore_wince_window_suspend_set(Ecore_WinCE_Window *window, int (*suspend)(int))
+{
+   struct _Ecore_WinCE_Window *w;
+
+   if (!window)
+     return;
+
+   INF("setting suspend callback");
+
+   w = (struct _Ecore_WinCE_Window *)window;
+   w->suspend = suspend;
+}
+
+void
+ecore_wince_window_resume_set(Ecore_WinCE_Window *window, int (*resume)(int))
+{
+   struct _Ecore_WinCE_Window *w;
+
+   if (!window)
+     return;
+
+   INF("setting resume callback");
+
+   w = (struct _Ecore_WinCE_Window *)window;
+   w->resume = resume;
+}
+
+void
+ecore_wince_window_geometry_get(Ecore_WinCE_Window *window,
+                                int                *x,
+                                int                *y,
+                                int                *width,
+                                int                *height)
+{
+   RECT rect;
+   int  w;
+   int  h;
+
+   INF("getting window geometry");
+
+   if (!window)
+     {
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = GetSystemMetrics(SM_CXSCREEN);
+        if (height) *height = GetSystemMetrics(SM_CYSCREEN);
+
+        return;
+     }
+
+   if (!GetClientRect(((struct _Ecore_WinCE_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetClientRect() failed");
+
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = 0;
+        if (height) *height = 0;
+
+        return;
+     }
+
+   w = rect.right - rect.left;
+   h = rect.bottom - rect.top;
+
+   if (!GetWindowRect(((struct _Ecore_WinCE_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetWindowRect() failed");
+
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = 0;
+        if (height) *height = 0;
+
+        return;
+     }
+
+   if (x) *x = rect.left;
+   if (y) *y = rect.top;
+   if (width) *width = w;
+   if (height) *height = h;
+}
+
+void
+ecore_wince_window_size_get(Ecore_WinCE_Window *window,
+                            int                *width,
+                            int                *height)
+{
+   RECT rect;
+
+   INF("getting window size");
+
+   if (!window)
+     {
+        if (width) *width = GetSystemMetrics(SM_CXSCREEN);
+        if (height) *height = GetSystemMetrics(SM_CYSCREEN);
+
+        return;
+     }
+
+   if (!GetClientRect(((struct _Ecore_WinCE_Window *)window)->window,
+                      &rect))
+     {
+        ERR("GetClientRect() failed");
+
+        if (width) *width = 0;
+        if (height) *height = 0;
+     }
+
+   if (width) *width = rect.right - rect.left;
+   if (height) *height = rect.bottom - rect.top;
+}
+
+void
+ecore_wince_window_fullscreen_set(Ecore_WinCE_Window *window,
+                                  int                 on)
+{
+   struct _Ecore_WinCE_Window *ew;
+   HWND                        w;
+   HWND                        task_bar;
+
+   if (!window) return;
+
+   ew = (struct _Ecore_WinCE_Window *)window;
+   if (((ew->fullscreen) && (on)) ||
+       ((!ew->fullscreen) && (!on)))
+     return;
+
+   INF("setting fullscreen: %s", on ? "yes" : "no");
+
+   ew->fullscreen = !!on;
+   w = ew->window;
+
+   if (on)
+     {
+        /* save the position and size of the window */
+        if (!GetWindowRect(w, &ew->rect))
+          {
+             ERR("GetWindowRect() failed");
+             return;
+          }
+
+        /* hide task bar */
+        task_bar = FindWindow(L"HHTaskBar", NULL);
+        if (!task_bar)
+          {
+             INF("FindWindow(): can not find task bar");
+          }
+        if (!ShowWindow(task_bar, SW_HIDE))
+          {
+             INF("ShowWindow(): task bar already hidden");
+          }
+        if (!EnableWindow(task_bar, FALSE))
+          {
+             INF("EnableWindow(): input already disabled");
+          }
+
+        /* style: visible + popup */
+        if (!SetWindowLong(w, GWL_STYLE, WS_POPUP | WS_VISIBLE))
+          {
+             INF("SetWindowLong() failed");
+          }
+
+        /* resize window to fit the entire screen */
+        if (!SetWindowPos(w, HWND_TOPMOST,
+                          0, 0,
+                          GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
+                          SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED))
+          {
+             INF("SetWindowPos() failed");
+          }
+        /*
+         * It seems that SetWindowPos is not sufficient.
+         * Call MoveWindow with the correct size and force painting.
+         * Note that UpdateWindow (forcing repainting) is not sufficient
+         */
+        if (!MoveWindow(w,
+                        0, 0,
+                        GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
+                        TRUE))
+          {
+             INF("MoveWindow() failed");
+          }
+     }
+   else
+     {
+        /* show task bar */
+        task_bar = FindWindow(L"HHTaskBar", NULL);
+        if (!task_bar)
+          {
+             INF("FindWindow(): can not find task bar");
+          }
+        if (!ShowWindow(task_bar, SW_SHOW))
+          {
+             INF("ShowWindow(): task bar already visible");
+          }
+        if (!EnableWindow(task_bar, TRUE))
+          {
+             INF("EnableWindow():  input already enabled");
+          }
+
+        /* style: visible + caption + sysmenu */
+        if (!SetWindowLong(w, GWL_STYLE, WS_CAPTION | WS_SYSMENU | WS_VISIBLE))
+          {
+             INF("SetWindowLong() failed");
+          }
+        /* restaure the position and size of the window */
+        if (!SetWindowPos(w, HWND_TOPMOST,
+                          ew->rect.left,
+                          ew->rect.top,
+                          ew->rect.right - ew->rect.left,
+                          ew->rect.bottom - ew->rect.top,
+                          SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED))
+          {
+             INF("SetWindowLong() failed");
+          }
+        /*
+         * It seems that SetWindowPos is not sufficient.
+         * Call MoveWindow with the correct size and force painting.
+         * Note that UpdateWindow (forcing repainting) is not sufficient
+         */
+        if (!MoveWindow(w,
+                        ew->rect.left,
+                        ew->rect.top,
+                        ew->rect.right - ew->rect.left,
+                        ew->rect.bottom - ew->rect.top,
+                        TRUE))
+          {
+             INF("MoveWindow() failed");
+          }
+     }
+}
+
+
+/***** Private functions definitions *****/
+
+static int
+_ecore_wince_hardware_keys_register(HWND window)
+{
+   HINSTANCE           core_dll;
+   UnregisterFunc1Proc unregister_fct;
+   int                 i;
+
+   core_dll = LoadLibrary(L"coredll.dll");
+   if (!core_dll)
+     {
+        ERR("LoadLibrary() failed");
+        return 0;
+     }
+
+   unregister_fct = (UnregisterFunc1Proc)GetProcAddress(core_dll, L"UnregisterFunc1");
+   if (!unregister_fct)
+     {
+        ERR("GetProcAddress() failed");
+        FreeLibrary(core_dll);
+        return 0;
+     }
+
+   for (i = 0xc1; i <= 0xcf; i++)
+     {
+        unregister_fct(MOD_WIN, i);
+        RegisterHotKey(window, i, MOD_WIN, i);
+     }
+
+   FreeLibrary(core_dll);
+
+   return 1;
+}
diff --git a/src/lib/ecore_x/.cvsignore b/src/lib/ecore_x/.cvsignore
new file mode 100644 (file)
index 0000000..8728e80
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_x.la
diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h
new file mode 100644 (file)
index 0000000..a8fe707
--- /dev/null
@@ -0,0 +1,1884 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifndef _ECORE_X_H
+#define _ECORE_X_H
+
+#include <Eina.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _MSC_VER
+# ifdef BUILDING_DLL
+#  define EAPI __declspec(dllexport)
+# else
+#  define EAPI __declspec(dllimport)
+# endif
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif
+
+#include <sys/types.h>
+
+/**
+ * @file
+ * @brief Ecore functions for dealing with the X Windows System
+ *
+ * Ecore_X provides a wrapper and convenience functions for using the
+ * X Windows System.  Function groups for this part of the library
+ * include the following:
+ * @li @ref Ecore_X_Init_Group
+ * @li @ref Ecore_X_Display_Attr_Group
+ * @li @ref Ecore_X_Flush_Group
+ */
+
+
+typedef unsigned int Ecore_X_ID;
+#ifndef _ECORE_X_WINDOW_PREDEF
+typedef Ecore_X_ID   Ecore_X_Window;
+#endif
+#ifdef HAVE_ECORE_X_XCB
+typedef Ecore_X_ID   Ecore_X_Visual;
+#else
+typedef void       * Ecore_X_Visual;
+#endif /* HAVE_ECORE_X_XCB */
+typedef Ecore_X_ID   Ecore_X_Pixmap;
+typedef Ecore_X_ID   Ecore_X_Drawable;
+#ifdef HAVE_ECORE_X_XCB
+typedef Ecore_X_ID   Ecore_X_GC;
+#else
+typedef void       * Ecore_X_GC;
+#endif /* HAVE_ECORE_X_XCB */
+typedef Ecore_X_ID   Ecore_X_Atom;
+typedef Ecore_X_ID   Ecore_X_Colormap;
+typedef Ecore_X_ID   Ecore_X_Time;
+typedef Ecore_X_ID   Ecore_X_Cursor;
+typedef void         Ecore_X_Display;
+typedef void         Ecore_X_Connection;
+typedef void         Ecore_X_Screen;
+typedef Ecore_X_ID   Ecore_X_Sync_Counter;
+typedef Ecore_X_ID   Ecore_X_Sync_Alarm;
+typedef void         Ecore_X_XRegion;
+
+typedef Ecore_X_ID     Ecore_X_Randr_Output;
+typedef Ecore_X_ID     Ecore_X_Randr_Crtc;
+typedef Ecore_X_ID     Ecore_X_Randr_Mode;
+typedef unsigned short Ecore_X_Randr_Size_ID;
+
+typedef Ecore_X_ID   Ecore_X_Device;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Ecore_X_Rectangle {
+   int x, y;
+   unsigned int width, height;
+} Ecore_X_Rectangle;
+
+typedef struct _Ecore_X_Icon {
+   unsigned int  width, height;
+   unsigned int *data;
+} Ecore_X_Icon;
+
+typedef enum _Ecore_X_GC_Value_Mask {
+   ECORE_X_GC_VALUE_MASK_FUNCTION = (1L << 0),
+   ECORE_X_GC_VALUE_MASK_PLANE_MASK = (1L << 1),
+   ECORE_X_GC_VALUE_MASK_FOREGROUND = (1L << 2),
+   ECORE_X_GC_VALUE_MASK_BACKGROUND = (1L << 3),
+   ECORE_X_GC_VALUE_MASK_LINE_WIDTH = (1L << 4),
+   ECORE_X_GC_VALUE_MASK_LINE_STYLE = (1L << 5),
+   ECORE_X_GC_VALUE_MASK_CAP_STYLE = (1L << 6),
+   ECORE_X_GC_VALUE_MASK_JOIN_STYLE = (1L << 7),
+   ECORE_X_GC_VALUE_MASK_FILL_STYLE = (1L << 8),
+   ECORE_X_GC_VALUE_MASK_FILL_RULE = (1L << 9),
+   ECORE_X_GC_VALUE_MASK_TILE = (1L << 10),
+   ECORE_X_GC_VALUE_MASK_STIPPLE = (1L << 11),
+   ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_X = (1L << 12),
+   ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_Y = (1L << 13),
+   ECORE_X_GC_VALUE_MASK_FONT = (1L << 14),
+   ECORE_X_GC_VALUE_MASK_SUBWINDOW_MODE = (1L << 15),
+   ECORE_X_GC_VALUE_MASK_GRAPHICS_EXPOSURES = (1L << 16),
+   ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_X = (1L << 17),
+   ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_Y = (1L << 18),
+   ECORE_X_GC_VALUE_MASK_CLIP_MASK = (1L << 19),
+   ECORE_X_GC_VALUE_MASK_DASH_OFFSET = (1L << 20),
+   ECORE_X_GC_VALUE_MASK_DASH_LIST = (1L << 21),
+   ECORE_X_GC_VALUE_MASK_ARC_MODE = (1L << 22)
+} Ecore_X_GC_Value_Mask;
+
+typedef enum _Ecore_X_Composite_Update_Type {
+   ECORE_X_COMPOSITE_UPDATE_AUTOMATIC,
+   ECORE_X_COMPOSITE_UPDATE_MANUAL
+} Ecore_X_Composite_Update_Type;
+
+typedef enum _Ecore_X_Window_State {
+    /* Unknown state */
+    ECORE_X_WINDOW_STATE_UNKNOWN = 0,
+    /** The window is iconified. */
+    ECORE_X_WINDOW_STATE_ICONIFIED,
+    /** The window is a modal dialog box. */
+    ECORE_X_WINDOW_STATE_MODAL,
+    /** The window manager should keep the window's position fixed
+     * even if the virtual desktop scrolls. */
+    ECORE_X_WINDOW_STATE_STICKY,
+    /** The window has the maximum vertical size. */
+    ECORE_X_WINDOW_STATE_MAXIMIZED_VERT,
+    /** The window has the maximum horizontal size. */
+    ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ,
+    /** The window is shaded. */
+    ECORE_X_WINDOW_STATE_SHADED,
+    /** The window should not be included in the taskbar. */
+    ECORE_X_WINDOW_STATE_SKIP_TASKBAR,
+    /** The window should not be included in the pager. */
+    ECORE_X_WINDOW_STATE_SKIP_PAGER,
+    /** The window is invisible (i.e. minimized/iconified) */
+    ECORE_X_WINDOW_STATE_HIDDEN,
+    /** The window should fill the entire screen and have no
+     * window border/decorations */
+    ECORE_X_WINDOW_STATE_FULLSCREEN,
+    /* The following are not documented because they are not
+     * intended for use in applications. */
+    ECORE_X_WINDOW_STATE_ABOVE,
+    ECORE_X_WINDOW_STATE_BELOW,
+    /* FIXME: Documentation */
+    ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION
+} Ecore_X_Window_State;
+
+typedef enum _Ecore_X_Window_State_Action {
+     ECORE_X_WINDOW_STATE_ACTION_REMOVE,
+     ECORE_X_WINDOW_STATE_ACTION_ADD,
+     ECORE_X_WINDOW_STATE_ACTION_TOGGLE
+} Ecore_X_Window_State_Action;
+
+typedef enum _Ecore_X_Window_Stack_Mode {
+   ECORE_X_WINDOW_STACK_ABOVE = 0,
+   ECORE_X_WINDOW_STACK_BELOW = 1,
+   ECORE_X_WINDOW_STACK_TOP_IF = 2,
+   ECORE_X_WINDOW_STACK_BOTTOM_IF = 3,
+   ECORE_X_WINDOW_STACK_OPPOSITE = 4
+} Ecore_X_Window_Stack_Mode;
+
+typedef enum _Ecore_X_Randr_Rotation {
+   ECORE_X_RANDR_ROT_0 = (1 << 0),
+   ECORE_X_RANDR_ROT_90 = (1 << 1),
+   ECORE_X_RANDR_ROT_180 = (1 << 2),
+   ECORE_X_RANDR_ROT_270 = (1 << 3),
+   ECORE_X_RANDR_FLIP_X = (1 << 4),
+   ECORE_X_RANDR_FLIP_Y = (1 << 5)
+} Ecore_X_Randr_Rotation;
+
+typedef enum _Ecore_X_Randr_Connection {
+  ECORE_X_RANDR_CONNECTED = 0,
+  ECORE_X_RANDR_DISCONNECTED = 1,
+  ECORE_X_RANDR_UNKNOWN_CONNECTION = 2
+} Ecore_X_Randr_Connection;
+
+typedef enum _Ecore_X_Render_Subpixel_Order {
+   ECORE_X_RENDER_SUBPIXEL_ORDER_UNKNOWN = 0,
+   ECORE_X_RENDER_SUBPIXEL_ORDER_HORIZONTAL_RGB = 1,
+   ECORE_X_RENDER_SUBPIXEL_ORDER_HORIZONTAL_BGR = 2,
+   ECORE_X_RENDER_SUBPIXEL_ORDER_VERTICAL_RGB = 3,
+   ECORE_X_RENDER_SUBPIXEL_ORDER_VERTICAL_BGR = 4,
+   ECORE_X_RENDER_SUBPIXEL_ORDER_NONE = 5
+} Ecore_X_Render_Subpixel_Order;
+
+#define ECORE_X_SELECTION_TARGET_TARGETS "TARGETS"
+#define ECORE_X_SELECTION_TARGET_TEXT "TEXT"
+#define ECORE_X_SELECTION_TARGET_COMPOUND_TEXT "COMPOUND_TEXT"
+#define ECORE_X_SELECTION_TARGET_STRING "STRING"
+#define ECORE_X_SELECTION_TARGET_UTF8_STRING "UTF8_STRING"
+#define ECORE_X_SELECTION_TARGET_FILENAME "FILENAME"
+
+#define ECORE_X_DND_VERSION 5
+
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_COPY;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_MOVE;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_LINK;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_ASK;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE;
+
+typedef enum _Ecore_X_Selection {
+   ECORE_X_SELECTION_PRIMARY,
+   ECORE_X_SELECTION_SECONDARY,
+   ECORE_X_SELECTION_XDND,
+   ECORE_X_SELECTION_CLIPBOARD,
+   ECORE_X_SELECTION_OTHER
+} Ecore_X_Selection;
+
+typedef enum _Ecore_X_Event_Mode
+{
+   ECORE_X_EVENT_MODE_NORMAL,
+   ECORE_X_EVENT_MODE_WHILE_GRABBED,
+   ECORE_X_EVENT_MODE_GRAB,
+   ECORE_X_EVENT_MODE_UNGRAB
+} Ecore_X_Event_Mode;
+
+typedef enum _Ecore_X_Event_Detail
+{
+   ECORE_X_EVENT_DETAIL_ANCESTOR,
+   ECORE_X_EVENT_DETAIL_VIRTUAL,
+   ECORE_X_EVENT_DETAIL_INFERIOR,
+   ECORE_X_EVENT_DETAIL_NON_LINEAR,
+   ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL,
+   ECORE_X_EVENT_DETAIL_POINTER,
+   ECORE_X_EVENT_DETAIL_POINTER_ROOT,
+   ECORE_X_EVENT_DETAIL_DETAIL_NONE
+} Ecore_X_Event_Detail;
+
+typedef enum _Ecore_X_Event_Mask
+{
+   ECORE_X_EVENT_MASK_NONE                   = 0L,
+   ECORE_X_EVENT_MASK_KEY_DOWN               = (1L << 0),
+   ECORE_X_EVENT_MASK_KEY_UP                 = (1L << 1),
+   ECORE_X_EVENT_MASK_MOUSE_DOWN             = (1L << 2),
+   ECORE_X_EVENT_MASK_MOUSE_UP               = (1L << 3),
+   ECORE_X_EVENT_MASK_MOUSE_IN               = (1L << 4),
+   ECORE_X_EVENT_MASK_MOUSE_OUT              = (1L << 5),
+   ECORE_X_EVENT_MASK_MOUSE_MOVE             = (1L << 6),
+   ECORE_X_EVENT_MASK_WINDOW_DAMAGE          = (1L << 15),
+   ECORE_X_EVENT_MASK_WINDOW_VISIBILITY      = (1L << 16),
+   ECORE_X_EVENT_MASK_WINDOW_CONFIGURE       = (1L << 17),
+   ECORE_X_EVENT_MASK_WINDOW_RESIZE_MANAGE   = (1L << 18),
+   ECORE_X_EVENT_MASK_WINDOW_MANAGE          = (1L << 19),
+   ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE = (1L << 20),
+   ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE    = (1L << 21),
+   ECORE_X_EVENT_MASK_WINDOW_PROPERTY        = (1L << 22),
+   ECORE_X_EVENT_MASK_WINDOW_COLORMAP        = (1L << 23),
+   ECORE_X_EVENT_MASK_WINDOW_GRAB            = (1L << 24),
+   ECORE_X_EVENT_MASK_MOUSE_WHEEL            = (1L << 29),
+   ECORE_X_EVENT_MASK_WINDOW_FOCUS_IN        = (1L << 30),
+   ECORE_X_EVENT_MASK_WINDOW_FOCUS_OUT       = (1L << 31)
+} Ecore_X_Event_Mask;
+
+typedef enum _Ecore_X_Gravity
+{
+   ECORE_X_GRAVITY_FORGET = 0,
+   ECORE_X_GRAVITY_UNMAP = 0,
+   ECORE_X_GRAVITY_NW = 1,
+   ECORE_X_GRAVITY_N = 2,
+   ECORE_X_GRAVITY_NE = 3,
+   ECORE_X_GRAVITY_W = 4,
+   ECORE_X_GRAVITY_CENTER = 5,
+   ECORE_X_GRAVITY_E = 6,
+   ECORE_X_GRAVITY_SW = 7,
+   ECORE_X_GRAVITY_S = 8,
+   ECORE_X_GRAVITY_SE = 9,
+   ECORE_X_GRAVITY_STATIC = 10
+} Ecore_X_Gravity;
+
+/* Needed for ecore_x_region_window_shape_set */
+typedef enum _Ecore_X_Shape_Type
+{
+   ECORE_X_SHAPE_BOUNDING,
+   ECORE_X_SHAPE_CLIP
+} Ecore_X_Shape_Type;
+
+typedef struct _Ecore_X_Event_Mouse_In                 Ecore_X_Event_Mouse_In;
+typedef struct _Ecore_X_Event_Mouse_Out                Ecore_X_Event_Mouse_Out;
+typedef struct _Ecore_X_Event_Window_Focus_In          Ecore_X_Event_Window_Focus_In;
+typedef struct _Ecore_X_Event_Window_Focus_Out         Ecore_X_Event_Window_Focus_Out;
+typedef struct _Ecore_X_Event_Window_Keymap            Ecore_X_Event_Window_Keymap;
+typedef struct _Ecore_X_Event_Window_Damage            Ecore_X_Event_Window_Damage;
+typedef struct _Ecore_X_Event_Window_Visibility_Change Ecore_X_Event_Window_Visibility_Change;
+typedef struct _Ecore_X_Event_Window_Create            Ecore_X_Event_Window_Create;
+typedef struct _Ecore_X_Event_Window_Destroy           Ecore_X_Event_Window_Destroy;
+typedef struct _Ecore_X_Event_Window_Hide              Ecore_X_Event_Window_Hide;
+typedef struct _Ecore_X_Event_Window_Show              Ecore_X_Event_Window_Show;
+typedef struct _Ecore_X_Event_Window_Show_Request      Ecore_X_Event_Window_Show_Request;
+typedef struct _Ecore_X_Event_Window_Reparent          Ecore_X_Event_Window_Reparent;
+typedef struct _Ecore_X_Event_Window_Configure         Ecore_X_Event_Window_Configure;
+typedef struct _Ecore_X_Event_Window_Configure_Request Ecore_X_Event_Window_Configure_Request;
+typedef struct _Ecore_X_Event_Window_Gravity           Ecore_X_Event_Window_Gravity;
+typedef struct _Ecore_X_Event_Window_Resize_Request    Ecore_X_Event_Window_Resize_Request;
+typedef struct _Ecore_X_Event_Window_Stack             Ecore_X_Event_Window_Stack;
+typedef struct _Ecore_X_Event_Window_Stack_Request     Ecore_X_Event_Window_Stack_Request;
+typedef struct _Ecore_X_Event_Window_Property          Ecore_X_Event_Window_Property;
+typedef struct _Ecore_X_Event_Window_Colormap          Ecore_X_Event_Window_Colormap;
+typedef struct _Ecore_X_Event_Window_Mapping           Ecore_X_Event_Window_Mapping;
+typedef struct _Ecore_X_Event_Selection_Clear          Ecore_X_Event_Selection_Clear;
+typedef struct _Ecore_X_Event_Selection_Request        Ecore_X_Event_Selection_Request;
+typedef struct _Ecore_X_Event_Selection_Notify         Ecore_X_Event_Selection_Notify;
+typedef struct _Ecore_X_Selection_Data                 Ecore_X_Selection_Data;
+typedef struct _Ecore_X_Selection_Data_Files           Ecore_X_Selection_Data_Files;
+typedef struct _Ecore_X_Selection_Data_Text            Ecore_X_Selection_Data_Text;
+typedef struct _Ecore_X_Selection_Data_Targets         Ecore_X_Selection_Data_Targets;
+typedef struct _Ecore_X_Event_Xdnd_Enter               Ecore_X_Event_Xdnd_Enter;
+typedef struct _Ecore_X_Event_Xdnd_Position            Ecore_X_Event_Xdnd_Position;
+typedef struct _Ecore_X_Event_Xdnd_Status              Ecore_X_Event_Xdnd_Status;
+typedef struct _Ecore_X_Event_Xdnd_Leave               Ecore_X_Event_Xdnd_Leave;
+typedef struct _Ecore_X_Event_Xdnd_Drop                Ecore_X_Event_Xdnd_Drop;
+typedef struct _Ecore_X_Event_Xdnd_Finished            Ecore_X_Event_Xdnd_Finished;
+typedef struct _Ecore_X_Event_Client_Message           Ecore_X_Event_Client_Message;
+typedef struct _Ecore_X_Event_Window_Shape             Ecore_X_Event_Window_Shape;
+typedef struct _Ecore_X_Event_Screensaver_Notify       Ecore_X_Event_Screensaver_Notify;
+typedef struct _Ecore_X_Event_Sync_Counter             Ecore_X_Event_Sync_Counter;
+typedef struct _Ecore_X_Event_Sync_Alarm               Ecore_X_Event_Sync_Alarm;
+typedef struct _Ecore_X_Event_Screen_Change            Ecore_X_Event_Screen_Change;
+typedef struct _Ecore_X_Event_Randr_Crtc_Change            Ecore_X_Event_Randr_Crtc_Change;
+typedef struct _Ecore_X_Event_Randr_Output_Change          Ecore_X_Event_Randr_Output_Change;
+typedef struct _Ecore_X_Event_Randr_Output_Property_Notify Ecore_X_Event_Randr_Output_Property_Notify;
+
+typedef struct _Ecore_X_Event_Window_Delete_Request                Ecore_X_Event_Window_Delete_Request;
+typedef struct _Ecore_X_Event_Window_Prop_Title_Change             Ecore_X_Event_Window_Prop_Title_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Visible_Title_Change     Ecore_X_Event_Window_Prop_Visible_Title_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Icon_Name_Change         Ecore_X_Event_Window_Prop_Icon_Name_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Client_Machine_Change    Ecore_X_Event_Window_Prop_Client_Machine_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Name_Class_Change        Ecore_X_Event_Window_Prop_Name_Class_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Pid_Change               Ecore_X_Event_Window_Prop_Pid_Change;
+typedef struct _Ecore_X_Event_Window_Prop_Desktop_Change           Ecore_X_Event_Window_Prop_Desktop_Change;
+
+typedef struct _Ecore_X_Event_Window_Move_Resize_Request Ecore_X_Event_Window_Move_Resize_Request;
+typedef struct _Ecore_X_Event_Window_State_Request       Ecore_X_Event_Window_State_Request;
+typedef struct _Ecore_X_Event_Frame_Extents_Request      Ecore_X_Event_Frame_Extents_Request;
+typedef struct _Ecore_X_Event_Ping                       Ecore_X_Event_Ping;
+typedef struct _Ecore_X_Event_Desktop_Change             Ecore_X_Event_Desktop_Change;
+
+typedef struct _Ecore_X_Event_Startup_Sequence           Ecore_X_Event_Startup_Sequence;
+
+typedef struct _Ecore_X_Event_Generic                    Ecore_X_Event_Generic;
+
+struct _Ecore_X_Event_Mouse_In
+{
+   int                  modifiers;
+   int                  x, y;
+   int                 same_screen;
+   struct {
+      int  x, y;
+   } root;
+   Ecore_X_Window               win;
+   Ecore_X_Window               event_win;
+   Ecore_X_Window              root_win;
+   Ecore_X_Event_Mode          mode;
+   Ecore_X_Event_Detail                detail;
+   Ecore_X_Time                 time;
+};
+
+struct _Ecore_X_Event_Mouse_Out
+{
+   int                  modifiers;
+   int                  x, y;
+   int                 same_screen;
+   struct {
+      int  x, y;
+   } root;
+   Ecore_X_Window               win;
+   Ecore_X_Window               event_win;
+   Ecore_X_Window              root_win;
+   Ecore_X_Event_Mode          mode;
+   Ecore_X_Event_Detail                detail;
+   Ecore_X_Time                 time;
+};
+
+struct _Ecore_X_Event_Window_Focus_In
+{
+   Ecore_X_Window       win;
+   Ecore_X_Event_Mode   mode;
+   Ecore_X_Event_Detail detail;
+   Ecore_X_Time         time;
+};
+
+struct _Ecore_X_Event_Window_Focus_Out
+{
+   Ecore_X_Window       win;
+   Ecore_X_Event_Mode   mode;
+   Ecore_X_Event_Detail detail;
+   Ecore_X_Time         time;
+};
+
+struct _Ecore_X_Event_Window_Keymap
+{
+   Ecore_X_Window  win;
+};
+
+struct _Ecore_X_Event_Window_Damage
+{
+   Ecore_X_Window  win;
+   int             x, y, w, h;
+   int             count;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Visibility_Change
+{
+   Ecore_X_Window  win;
+   int             fully_obscured;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Create
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  parent;
+   int             override;
+   int             x, y, w, h;
+   int             border;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Destroy
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Hide
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Show
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Show_Request
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  parent;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Reparent
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win; 
+   Ecore_X_Window  parent;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Configure
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Window  abovewin;
+   int             x, y, w, h;
+   int             border;
+   unsigned int    override : 1;
+   unsigned int    from_wm : 1;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Configure_Request
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  parent_win;
+   Ecore_X_Window  abovewin;
+   int             x, y, w, h;
+   int             border;
+   Ecore_X_Window_Stack_Mode detail;
+   unsigned long   value_mask;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Gravity
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Resize_Request
+{
+   Ecore_X_Window  win;
+   int             w, h;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Stack
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Window_Stack_Mode detail;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Stack_Request
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  parent;
+   Ecore_X_Window_Stack_Mode detail;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Property
+{
+   Ecore_X_Window  win;
+   Ecore_X_Atom    atom;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Colormap
+{
+   Ecore_X_Window   win;
+   Ecore_X_Colormap cmap;
+   int              installed;
+   Ecore_X_Time     time;
+};
+
+struct _Ecore_X_Event_Selection_Clear
+{
+   Ecore_X_Window    win;
+   Ecore_X_Selection selection;
+   Ecore_X_Atom      atom;
+   Ecore_X_Time      time;
+};
+
+struct _Ecore_X_Event_Selection_Request
+{
+   Ecore_X_Window    owner;
+   Ecore_X_Window    requestor;
+   Ecore_X_Time      time;
+   Ecore_X_Atom      selection;
+   Ecore_X_Atom      target;
+   Ecore_X_Atom      property;
+};
+
+struct _Ecore_X_Event_Selection_Notify
+{
+   Ecore_X_Window             win;
+   Ecore_X_Time               time;
+   Ecore_X_Selection          selection;
+   Ecore_X_Atom               atom;
+   char                      *target;
+   void                      *data;
+};
+
+struct _Ecore_X_Selection_Data
+{
+   enum {
+       ECORE_X_SELECTION_CONTENT_NONE,
+       ECORE_X_SELECTION_CONTENT_TEXT,
+       ECORE_X_SELECTION_CONTENT_FILES,
+       ECORE_X_SELECTION_CONTENT_TARGETS,
+       ECORE_X_SELECTION_CONTENT_CUSTOM
+   } content;
+   unsigned char    *data;
+   int               length;
+   int               format;
+
+   int             (*free)(void *data);
+};
+
+struct _Ecore_X_Selection_Data_Files
+{
+   Ecore_X_Selection_Data data;
+   char     **files;
+   int        num_files;
+};
+
+struct _Ecore_X_Selection_Data_Text
+{
+   Ecore_X_Selection_Data data;
+   char     *text;
+};
+
+struct _Ecore_X_Selection_Data_Targets
+{
+   Ecore_X_Selection_Data data;
+   char     **targets;
+   int        num_targets;
+};
+
+struct _Ecore_X_Event_Xdnd_Enter
+{
+   Ecore_X_Window       win, source;
+
+   char               **types;
+   int                  num_types;
+};
+
+struct _Ecore_X_Event_Xdnd_Position
+{
+   Ecore_X_Window       win, source;
+   struct {
+      int x, y;
+   } position;
+   Ecore_X_Atom         action;
+};
+
+struct _Ecore_X_Event_Xdnd_Status
+{
+   Ecore_X_Window       win, target;
+   int                  will_accept;
+   Ecore_X_Rectangle    rectangle;
+   Ecore_X_Atom         action;
+};
+
+struct _Ecore_X_Event_Xdnd_Leave
+{
+   Ecore_X_Window       win, source;
+};
+
+struct _Ecore_X_Event_Xdnd_Drop
+{
+   Ecore_X_Window       win, source;
+   Ecore_X_Atom         action;
+   struct {
+      int x, y;
+   } position;
+};
+
+struct _Ecore_X_Event_Xdnd_Finished
+{
+   Ecore_X_Window       win, target;
+   int                  completed;
+   Ecore_X_Atom         action;
+};
+
+struct _Ecore_X_Event_Client_Message
+{
+   Ecore_X_Window       win;
+   Ecore_X_Atom         message_type;
+   int                  format;
+   union {
+      char              b[20];
+      short             s[10];
+      long              l[5];
+   }                    data;
+   Ecore_X_Time         time;
+};
+
+struct _Ecore_X_Event_Window_Shape
+{
+   Ecore_X_Window  win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Screensaver_Notify
+{
+   Ecore_X_Window  win;
+   int             on;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Sync_Counter
+{
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Sync_Alarm
+{
+   Ecore_X_Time       time;
+   Ecore_X_Sync_Alarm alarm;
+};
+
+struct _Ecore_X_Event_Screen_Change
+{
+   Ecore_X_Window                win;
+   Ecore_X_Window                root;
+   int                           width;
+   int                           height;
+   Ecore_X_Time                  time;
+   Ecore_X_Time                  config_time;
+   int                           mm_width;   /* in millimeters */
+   int                           mm_height;  /* in millimeters */
+   Ecore_X_Randr_Rotation        rotation;
+   Ecore_X_Render_Subpixel_Order subpixel_order;
+   Ecore_X_Randr_Size_ID         size_id;
+};
+
+struct _Ecore_X_Event_Randr_Crtc_Change
+{
+   Ecore_X_Window                win;
+   Ecore_X_Randr_Crtc            crtc;
+   Ecore_X_Randr_Mode            mode;
+   Ecore_X_Randr_Rotation        rotation;
+   int                           x;
+   int                           y;
+   int                           width;
+   int                           height;
+};
+
+struct _Ecore_X_Event_Randr_Output_Change
+{
+   Ecore_X_Window                win;
+   Ecore_X_Randr_Output          output;
+   Ecore_X_Randr_Crtc            crtc;
+   Ecore_X_Randr_Mode            mode;
+   Ecore_X_Randr_Rotation        rotation;
+   Ecore_X_Randr_Connection      connection;
+   Ecore_X_Render_Subpixel_Order subpixel_order;
+};
+
+struct _Ecore_X_Event_Randr_Output_Property_Notify
+{
+   Ecore_X_Window                win;
+   Ecore_X_Randr_Output          output;
+   Ecore_X_Atom                  property;
+   Ecore_X_Time                  time;
+   int                           state; /* NewValue, Deleted */
+};
+
+struct _Ecore_X_Event_Window_Delete_Request
+{
+   Ecore_X_Window  win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Title_Change
+{
+   Ecore_X_Window  win;
+   char   *title;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Visible_Title_Change
+{
+   Ecore_X_Window  win;
+   char   *title;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Icon_Name_Change
+{
+   Ecore_X_Window  win;
+   char   *name;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change
+{
+   Ecore_X_Window  win;
+   char   *name;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Client_Machine_Change
+{
+   Ecore_X_Window  win;
+   char   *name;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Name_Class_Change
+{
+   Ecore_X_Window  win;
+   char   *name;
+   char   *clas;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Pid_Change
+{
+   Ecore_X_Window  win;
+   pid_t   pid;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Window_Prop_Desktop_Change
+{
+   Ecore_X_Window  win;
+   long    desktop;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Startup_Sequence
+{
+   Ecore_X_Window  win;
+};
+
+struct _Ecore_X_Event_Window_Move_Resize_Request
+{
+   Ecore_X_Window win;
+   int            x, y;
+   int            direction;
+   int            button;
+   int            source;
+};
+
+struct _Ecore_X_Event_Window_State_Request
+{
+   Ecore_X_Window              win;
+   Ecore_X_Window_State_Action action;
+   Ecore_X_Window_State        state[2];
+   int                         source;
+};
+
+struct _Ecore_X_Event_Frame_Extents_Request
+{
+   Ecore_X_Window              win;
+};
+
+struct _Ecore_X_Event_Ping
+{
+   Ecore_X_Window  win;
+   Ecore_X_Window  event_win;
+   Ecore_X_Time    time;
+};
+
+struct _Ecore_X_Event_Desktop_Change
+{
+   Ecore_X_Window              win;
+   unsigned int                desk;
+   int                         source;
+};
+
+struct _Ecore_X_Event_Generic
+{
+   int            extension;
+   int            evtype;
+   unsigned int   cookie;
+   void           *data;
+};
+
+EAPI extern int ECORE_X_EVENT_ANY; /**< low level event dependent on
+                                       backend in use, if Xlib will be XEvent,
+                                       if XCB will be xcb_generic_event_t.
+                                       @warning avoid using it.
+                                  */
+EAPI extern int ECORE_X_EVENT_MOUSE_IN;
+EAPI extern int ECORE_X_EVENT_MOUSE_OUT;
+EAPI extern int ECORE_X_EVENT_WINDOW_FOCUS_IN;
+EAPI extern int ECORE_X_EVENT_WINDOW_FOCUS_OUT;
+EAPI extern int ECORE_X_EVENT_WINDOW_KEYMAP;
+EAPI extern int ECORE_X_EVENT_WINDOW_DAMAGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_CREATE;
+EAPI extern int ECORE_X_EVENT_WINDOW_DESTROY;
+EAPI extern int ECORE_X_EVENT_WINDOW_HIDE;
+EAPI extern int ECORE_X_EVENT_WINDOW_SHOW;
+EAPI extern int ECORE_X_EVENT_WINDOW_SHOW_REQUEST;
+EAPI extern int ECORE_X_EVENT_WINDOW_REPARENT;
+EAPI extern int ECORE_X_EVENT_WINDOW_CONFIGURE;
+EAPI extern int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST;
+EAPI extern int ECORE_X_EVENT_WINDOW_GRAVITY;
+EAPI extern int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST;
+EAPI extern int ECORE_X_EVENT_WINDOW_STACK;
+EAPI extern int ECORE_X_EVENT_WINDOW_STACK_REQUEST;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROPERTY;
+EAPI extern int ECORE_X_EVENT_WINDOW_COLORMAP;
+EAPI extern int ECORE_X_EVENT_WINDOW_MAPPING;
+EAPI extern int ECORE_X_EVENT_SELECTION_CLEAR;
+EAPI extern int ECORE_X_EVENT_SELECTION_REQUEST;
+EAPI extern int ECORE_X_EVENT_SELECTION_NOTIFY;
+EAPI extern int ECORE_X_EVENT_CLIENT_MESSAGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_SHAPE;
+EAPI extern int ECORE_X_EVENT_SCREENSAVER_NOTIFY;
+EAPI extern int ECORE_X_EVENT_SYNC_COUNTER;
+EAPI extern int ECORE_X_EVENT_SYNC_ALARM;
+EAPI extern int ECORE_X_EVENT_SCREEN_CHANGE;
+EAPI extern int ECORE_X_EVENT_RANDR_CRTC_CHANGE;
+EAPI extern int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE;
+EAPI extern int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY;
+EAPI extern int ECORE_X_EVENT_DAMAGE_NOTIFY;
+
+EAPI extern int ECORE_X_EVENT_WINDOW_DELETE_REQUEST;
+/*
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE;
+EAPI extern int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE;
+*/
+
+EAPI extern int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST;
+EAPI extern int ECORE_X_EVENT_WINDOW_STATE_REQUEST;
+EAPI extern int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST;
+EAPI extern int ECORE_X_EVENT_PING;
+EAPI extern int ECORE_X_EVENT_DESKTOP_CHANGE;
+
+EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
+EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
+EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
+
+EAPI extern int ECORE_X_EVENT_GENERIC;
+
+EAPI extern int ECORE_X_EVENT_XDND_ENTER;
+EAPI extern int ECORE_X_EVENT_XDND_POSITION;
+EAPI extern int ECORE_X_EVENT_XDND_STATUS;
+EAPI extern int ECORE_X_EVENT_XDND_LEAVE;
+EAPI extern int ECORE_X_EVENT_XDND_DROP;
+EAPI extern int ECORE_X_EVENT_XDND_FINISHED;
+
+EAPI extern int ECORE_X_LOCK_SCROLL;
+EAPI extern int ECORE_X_LOCK_NUM;
+EAPI extern int ECORE_X_LOCK_CAPS;
+
+typedef enum _Ecore_X_WM_Protocol 
+{
+   /* If enabled the window manager will be asked to send a
+    * delete message instead of just closing (destroying) the window. */
+   ECORE_X_WM_PROTOCOL_DELETE_REQUEST,
+
+   /* If enabled the window manager will be told that the window
+    * explicitly sets input focus. */
+   ECORE_X_WM_PROTOCOL_TAKE_FOCUS,
+
+   /* If enabled the window manager can ping the window to check
+    * if it is alive. */
+   ECORE_X_NET_WM_PROTOCOL_PING,
+
+   /* If enabled the window manager can sync updating with the
+    * window (?) */
+   ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST,
+
+   /* Number of defined items */
+   ECORE_X_WM_PROTOCOL_NUM
+} Ecore_X_WM_Protocol;
+
+typedef enum _Ecore_X_Window_Input_Mode 
+{
+   /* The window can never be focused */
+   ECORE_X_WINDOW_INPUT_MODE_NONE,
+
+   /* The window can be focused by the WM but doesn't focus itself */
+   ECORE_X_WINDOW_INPUT_MODE_PASSIVE,
+
+   /* The window sets the focus itself if one of its sub-windows
+    * already is focused */
+   ECORE_X_WINDOW_INPUT_MODE_ACTIVE_LOCAL,
+
+   /* The window sets the focus itself even if another window
+    * is currently focused */
+   ECORE_X_WINDOW_INPUT_MODE_ACTIVE_GLOBAL
+} Ecore_X_Window_Input_Mode;
+
+typedef enum _Ecore_X_Window_State_Hint 
+{
+   /** Do not provide any state hint to the window manager */
+   ECORE_X_WINDOW_STATE_HINT_NONE = -1,
+
+   /** The window wants to remain hidden and NOT iconified */
+   ECORE_X_WINDOW_STATE_HINT_WITHDRAWN,
+
+   /** The window wants to be mapped normally */
+   ECORE_X_WINDOW_STATE_HINT_NORMAL,
+
+   /** The window wants to start in an iconified state */
+   ECORE_X_WINDOW_STATE_HINT_ICONIC
+} Ecore_X_Window_State_Hint;
+
+typedef enum _Ecore_X_Window_Type 
+{
+     ECORE_X_WINDOW_TYPE_UNKNOWN = 0,
+     ECORE_X_WINDOW_TYPE_DESKTOP,
+     ECORE_X_WINDOW_TYPE_DOCK,
+     ECORE_X_WINDOW_TYPE_TOOLBAR,
+     ECORE_X_WINDOW_TYPE_MENU,
+     ECORE_X_WINDOW_TYPE_UTILITY,
+     ECORE_X_WINDOW_TYPE_SPLASH,
+     ECORE_X_WINDOW_TYPE_DIALOG,
+     ECORE_X_WINDOW_TYPE_NORMAL,
+     ECORE_X_WINDOW_TYPE_DROPDOWN_MENU,
+     ECORE_X_WINDOW_TYPE_POPUP_MENU,
+     ECORE_X_WINDOW_TYPE_TOOLTIP,
+     ECORE_X_WINDOW_TYPE_NOTIFICATION,
+     ECORE_X_WINDOW_TYPE_COMBO,
+     ECORE_X_WINDOW_TYPE_DND
+} Ecore_X_Window_Type;
+
+typedef enum _Ecore_X_Action 
+{
+   ECORE_X_ACTION_MOVE,
+   ECORE_X_ACTION_RESIZE,
+   ECORE_X_ACTION_MINIMIZE,
+   ECORE_X_ACTION_SHADE,
+   ECORE_X_ACTION_STICK,
+   ECORE_X_ACTION_MAXIMIZE_HORZ,
+   ECORE_X_ACTION_MAXIMIZE_VERT,
+   ECORE_X_ACTION_FULLSCREEN,
+   ECORE_X_ACTION_CHANGE_DESKTOP,
+   ECORE_X_ACTION_CLOSE,
+   ECORE_X_ACTION_ABOVE,
+   ECORE_X_ACTION_BELOW
+} Ecore_X_Action;
+
+typedef enum _Ecore_X_Window_Configure_Mask 
+{
+   ECORE_X_WINDOW_CONFIGURE_MASK_X = (1 << 0),
+   ECORE_X_WINDOW_CONFIGURE_MASK_Y = (1 << 1),
+   ECORE_X_WINDOW_CONFIGURE_MASK_W = (1 << 2),
+   ECORE_X_WINDOW_CONFIGURE_MASK_H = (1 << 3),
+   ECORE_X_WINDOW_CONFIGURE_MASK_BORDER_WIDTH = (1 << 4),
+   ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING = (1 << 5),
+   ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE = (1 << 6)
+} Ecore_X_Window_Configure_Mask;
+
+typedef enum _Ecore_X_Virtual_Keyboard_State 
+{
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN = 0,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_ON,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_IP,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_URL,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD,
+   ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME
+} Ecore_X_Virtual_Keyboard_State;
+
+typedef enum _Ecore_X_Illume_Mode 
+{
+   ECORE_X_ILLUME_MODE_UNKNOWN = 0, 
+   ECORE_X_ILLUME_MODE_SINGLE, 
+   ECORE_X_ILLUME_MODE_DUAL_TOP, 
+   ECORE_X_ILLUME_MODE_DUAL_LEFT
+} Ecore_X_Illume_Mode;
+
+typedef enum _Ecore_X_Illume_Quickpanel_State 
+{
+   ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN = 0, 
+   ECORE_X_ILLUME_QUICKPANEL_STATE_OFF, 
+   ECORE_X_ILLUME_QUICKPANEL_STATE_ON
+} Ecore_X_Illume_Quickpanel_State;
+
+/* Window layer constants */
+#define ECORE_X_WINDOW_LAYER_BELOW 2
+#define ECORE_X_WINDOW_LAYER_NORMAL 4
+#define ECORE_X_WINDOW_LAYER_ABOVE 6
+
+/* Property list operations */
+#define ECORE_X_PROP_LIST_REMOVE 0
+#define ECORE_X_PROP_LIST_ADD 1
+#define ECORE_X_PROP_LIST_TOGGLE 2
+
+EAPI int              ecore_x_init(const char *name);
+EAPI int              ecore_x_shutdown(void);
+EAPI int              ecore_x_disconnect(void);
+EAPI Ecore_X_Display *ecore_x_display_get(void);
+EAPI Ecore_X_Connection *ecore_x_connection_get(void);
+EAPI int              ecore_x_fd_get(void);
+EAPI Ecore_X_Screen  *ecore_x_default_screen_get(void);
+EAPI void             ecore_x_double_click_time_set(double t);
+EAPI double           ecore_x_double_click_time_get(void);
+EAPI void             ecore_x_flush(void);
+EAPI void             ecore_x_sync(void);
+EAPI void             ecore_x_killall(Ecore_X_Window root);
+EAPI void             ecore_x_kill(Ecore_X_Window win);
+EAPI int              ecore_x_dpi_get(void);
+
+EAPI Ecore_X_Time     ecore_x_current_time_get(void);
+
+EAPI void             ecore_x_error_handler_set(void (*func) (void *data), const void *data);
+EAPI void             ecore_x_io_error_handler_set(void (*func) (void *data), const void *data);
+EAPI int              ecore_x_error_request_get(void);
+EAPI int              ecore_x_error_code_get(void);
+
+EAPI void             ecore_x_event_mask_set(Ecore_X_Window w, Ecore_X_Event_Mask mask);
+EAPI void             ecore_x_event_mask_unset(Ecore_X_Window w, Ecore_X_Event_Mask mask);
+
+EAPI int              ecore_x_selection_notify_send(Ecore_X_Window requestor, Ecore_X_Atom selection, Ecore_X_Atom target, Ecore_X_Atom property, Ecore_X_Time time);
+EAPI void             ecore_x_selection_primary_prefetch(void);
+EAPI void             ecore_x_selection_primary_fetch(void);
+EAPI int              ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size);
+EAPI int              ecore_x_selection_primary_clear(void);
+EAPI void             ecore_x_selection_secondary_prefetch(void);
+EAPI void             ecore_x_selection_secondary_fetch(void);
+EAPI int              ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size);
+EAPI int              ecore_x_selection_secondary_clear(void);
+EAPI void             ecore_x_selection_xdnd_prefetch(void);
+EAPI void             ecore_x_selection_xdnd_fetch(void);
+EAPI int              ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size);
+EAPI int              ecore_x_selection_xdnd_clear(void);
+EAPI void             ecore_x_selection_clipboard_prefetch(void);
+EAPI void             ecore_x_selection_clipboard_fetch(void);
+EAPI int              ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size);
+EAPI int              ecore_x_selection_clipboard_clear(void);
+EAPI void             ecore_x_selection_primary_request(Ecore_X_Window w, const char *target);
+EAPI void             ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target);
+EAPI void             ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target);
+EAPI void             ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target);
+EAPI int              ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret);
+EAPI void             ecore_x_selection_converter_add(char *target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret));
+EAPI void             ecore_x_selection_converter_atom_add(Ecore_X_Atom target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret));
+EAPI void             ecore_x_selection_converter_del(char *target);
+EAPI void             ecore_x_selection_converter_atom_del(Ecore_X_Atom target);
+EAPI void             ecore_x_selection_parser_add(const char *target, void *(*func)(const char *target, void *data, int size, int format));
+EAPI void             ecore_x_selection_parser_del(const char *target);
+
+EAPI void             ecore_x_dnd_aware_set(Ecore_X_Window win, int on);
+EAPI void             ecore_x_dnd_version_get_prefetch(Ecore_X_Window window);
+EAPI void             ecore_x_dnd_version_get_fetch(void);
+EAPI int              ecore_x_dnd_version_get(Ecore_X_Window win);
+EAPI void             ecore_x_dnd_type_get_prefetch(Ecore_X_Window window);
+EAPI void             ecore_x_dnd_type_get_fetch(void);
+EAPI int              ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type);
+EAPI void             ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on);
+EAPI void             ecore_x_dnd_types_set(Ecore_X_Window win, const char **types, unsigned int num_types);
+EAPI void             ecore_x_dnd_actions_set(Ecore_X_Window win, Ecore_X_Atom *actions, unsigned int num_actions);
+EAPI void             ecore_x_dnd_begin_prefetch(Ecore_X_Window source);
+EAPI void             ecore_x_dnd_begin_fetch(void);
+EAPI int              ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size);
+EAPI int              ecore_x_dnd_drop(void);
+EAPI void             ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action);
+EAPI void             ecore_x_dnd_send_finished(void);
+EAPI void             ecore_x_dnd_source_action_set(Ecore_X_Atom action);
+EAPI Ecore_X_Atom     ecore_x_dnd_source_action_get(void);
+
+EAPI Ecore_X_Window   ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window   ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI int              ecore_x_window_argb_get(Ecore_X_Window win);
+EAPI Ecore_X_Window   ecore_x_window_manager_argb_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window   ecore_x_window_argb_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window   ecore_x_window_override_argb_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI Ecore_X_Window   ecore_x_window_input_new(Ecore_X_Window parent, int x, int y, int w, int h);
+EAPI void             ecore_x_window_configure(Ecore_X_Window win,
+                                              Ecore_X_Window_Configure_Mask mask,
+                                              int x, int y, int w, int h,
+                                              int border_width,
+                                              Ecore_X_Window sibling,
+                                              int stack_mode);
+EAPI void             ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c);
+EAPI void             ecore_x_window_free(Ecore_X_Window win);
+EAPI void             ecore_x_window_ignore_set(Ecore_X_Window win, int ignore);
+EAPI Ecore_X_Window  *ecore_x_window_ignore_list(int *num);
+
+EAPI void             ecore_x_window_delete_request_send(Ecore_X_Window win);
+EAPI void             ecore_x_window_show(Ecore_X_Window win);
+EAPI void             ecore_x_window_hide(Ecore_X_Window win);
+EAPI void             ecore_x_window_move(Ecore_X_Window win, int x, int y);
+EAPI void             ecore_x_window_resize(Ecore_X_Window win, int w, int h);
+EAPI void             ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI void             ecore_x_window_focus(Ecore_X_Window win);
+EAPI void             ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t);
+EAPI void             ecore_x_get_input_focus_prefetch(void);
+EAPI void             ecore_x_get_input_focus_fetch(void);
+EAPI Ecore_X_Window   ecore_x_window_focus_get(void);
+EAPI void             ecore_x_window_raise(Ecore_X_Window win);
+EAPI void             ecore_x_window_lower(Ecore_X_Window win);
+EAPI void             ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window new_parent, int x, int y);
+EAPI void             ecore_x_window_size_get(Ecore_X_Window win, int *w, int *h);
+EAPI void             ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h);
+EAPI int              ecore_x_window_border_width_get(Ecore_X_Window win);
+EAPI void             ecore_x_window_border_width_set(Ecore_X_Window win, int width);
+EAPI int              ecore_x_window_depth_get(Ecore_X_Window win);
+EAPI void             ecore_x_window_cursor_show(Ecore_X_Window win, int show);
+EAPI void             ecore_x_window_defaults_set(Ecore_X_Window win);
+EAPI int              ecore_x_window_visible_get(Ecore_X_Window win);
+EAPI Ecore_X_Window   ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num);
+EAPI Ecore_X_Window   ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win);
+EAPI void             ecore_x_window_shadow_tree_flush(void);
+EAPI Ecore_X_Window   ecore_x_window_root_get(Ecore_X_Window win);
+EAPI Ecore_X_Window   ecore_x_window_at_xy_get(int x, int y);
+EAPI Ecore_X_Window   ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num);
+EAPI Ecore_X_Window   ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y);
+EAPI void             ecore_x_query_tree_prefetch(Ecore_X_Window window);
+EAPI void             ecore_x_query_tree_fetch(void);
+EAPI Ecore_X_Window   ecore_x_window_parent_get(Ecore_X_Window win);
+
+EAPI void             ecore_x_window_background_color_set(Ecore_X_Window win,
+                                                         unsigned short r,
+                                                         unsigned short g,
+                                                         unsigned short b);
+EAPI void             ecore_x_window_gravity_set(Ecore_X_Window win,
+                                                Ecore_X_Gravity grav);
+EAPI void             ecore_x_window_pixel_gravity_set(Ecore_X_Window win,
+                                                      Ecore_X_Gravity grav);
+EAPI void             ecore_x_window_pixmap_set(Ecore_X_Window win,
+                                               Ecore_X_Pixmap pmap);
+EAPI void             ecore_x_window_area_clear(Ecore_X_Window win,
+                                               int x, int y, int w, int h);
+EAPI void             ecore_x_window_area_expose(Ecore_X_Window win,
+                                                int x, int y, int w, int h);
+EAPI void             ecore_x_window_override_set(Ecore_X_Window win, int override);
+
+EAPI void             ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                                                    unsigned int *val, unsigned int num);
+EAPI void             ecore_x_window_prop_card32_get_prefetch(Ecore_X_Window window,
+                                                              Ecore_X_Atom atom);
+EAPI void             ecore_x_window_prop_card32_get_fetch(void);
+EAPI int              ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                                                    unsigned int *val, unsigned int len);
+EAPI int              ecore_x_window_prop_card32_list_get(Ecore_X_Window win,
+                                                          Ecore_X_Atom atom,
+                                                          unsigned int **plst);
+
+EAPI void             ecore_x_window_prop_xid_set(Ecore_X_Window win,
+                                                  Ecore_X_Atom atom,
+                                                  Ecore_X_Atom type,
+                                                  Ecore_X_ID * lst,
+                                                  unsigned int num);
+EAPI void             ecore_x_window_prop_xid_get_prefetch(Ecore_X_Window window,
+                                                           Ecore_X_Atom   atom,
+                                                           Ecore_X_Atom   type);
+EAPI void             ecore_x_window_prop_xid_get_fetch(void);
+EAPI int              ecore_x_window_prop_xid_get(Ecore_X_Window win,
+                                                  Ecore_X_Atom atom,
+                                                  Ecore_X_Atom type,
+                                                  Ecore_X_ID * lst,
+                                                  unsigned int len);
+EAPI int              ecore_x_window_prop_xid_list_get(Ecore_X_Window win,
+                                                       Ecore_X_Atom atom,
+                                                       Ecore_X_Atom type,
+                                                       Ecore_X_ID ** plst);
+EAPI void             ecore_x_window_prop_xid_list_change(Ecore_X_Window win,
+                                                          Ecore_X_Atom atom,
+                                                          Ecore_X_Atom type,
+                                                          Ecore_X_ID item,
+                                                          int op);
+EAPI void             ecore_x_window_prop_atom_set(Ecore_X_Window win,
+                                                   Ecore_X_Atom atom,
+                                                   Ecore_X_Atom * val,
+                                                   unsigned int num);
+EAPI void             ecore_x_window_prop_atom_get_prefetch(Ecore_X_Window window,
+                                                            Ecore_X_Atom   atom);
+EAPI void             ecore_x_window_prop_atom_get_fetch(void);
+EAPI int              ecore_x_window_prop_atom_get(Ecore_X_Window win,
+                                                   Ecore_X_Atom atom,
+                                                   Ecore_X_Atom * val,
+                                                   unsigned int len);
+EAPI int              ecore_x_window_prop_atom_list_get(Ecore_X_Window win,
+                                                        Ecore_X_Atom atom,
+                                                        Ecore_X_Atom ** plst);
+EAPI void             ecore_x_window_prop_atom_list_change(Ecore_X_Window win,
+                                                           Ecore_X_Atom atom,
+                                                           Ecore_X_Atom item,
+                                                           int op);
+EAPI void             ecore_x_window_prop_window_set(Ecore_X_Window win,
+                                                     Ecore_X_Atom atom,
+                                                     Ecore_X_Window * val,
+                                                     unsigned int num);
+EAPI void             ecore_x_window_prop_window_get_prefetch(Ecore_X_Window window,
+                                                              Ecore_X_Atom   atom);
+EAPI void             ecore_x_window_prop_window_get_fetch(void);
+EAPI int              ecore_x_window_prop_window_get(Ecore_X_Window win,
+                                                     Ecore_X_Atom atom,
+                                                     Ecore_X_Window * val,
+                                                     unsigned int len);
+EAPI int              ecore_x_window_prop_window_list_get(Ecore_X_Window win,
+                                                          Ecore_X_Atom atom,
+                                                          Ecore_X_Window ** plst);
+
+EAPI Ecore_X_Atom     ecore_x_window_prop_any_type(void);
+EAPI void             ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Atom format, int size, void *data, int number);
+EAPI void             ecore_x_window_prop_property_get_prefetch(Ecore_X_Window window,
+                                                                Ecore_X_Atom   property,
+                                                                Ecore_X_Atom   type);
+EAPI void             ecore_x_window_prop_property_get_fetch(void);
+EAPI int              ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size, unsigned char **data, int *num);
+EAPI void             ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property);
+EAPI void             ecore_x_window_prop_list_prefetch(Ecore_X_Window window);
+EAPI void             ecore_x_window_prop_list_fetch(void);
+EAPI Ecore_X_Atom    *ecore_x_window_prop_list(Ecore_X_Window win, int *num_ret);
+EAPI void             ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str);
+EAPI void             ecore_x_window_prop_string_get_prefetch(Ecore_X_Window window,
+                                                              Ecore_X_Atom   type);
+EAPI void             ecore_x_window_prop_string_get_fetch(void);
+EAPI char            *ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type);
+EAPI int              ecore_x_window_prop_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol);
+EAPI Ecore_X_WM_Protocol *ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, int *num_ret);
+
+EAPI void               ecore_x_window_shape_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask);
+EAPI void               ecore_x_window_shape_window_set(Ecore_X_Window win, Ecore_X_Window shape_win);
+EAPI void               ecore_x_window_shape_window_set_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y);
+EAPI void               ecore_x_window_shape_rectangle_set(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI void               ecore_x_window_shape_rectangles_set(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num);
+EAPI void               ecore_x_window_shape_window_add(Ecore_X_Window win, Ecore_X_Window shape_win);
+EAPI void               ecore_x_window_shape_window_add_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y);
+EAPI void               ecore_x_window_shape_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI void               ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI void               ecore_x_window_shape_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num);
+EAPI void               ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Window window);
+EAPI void               ecore_x_window_shape_rectangles_get_fetch(void);
+EAPI Ecore_X_Rectangle *ecore_x_window_shape_rectangles_get(Ecore_X_Window win, int *num_ret);
+EAPI void               ecore_x_window_shape_events_select(Ecore_X_Window win, int on);
+EAPI void               ecore_x_window_shape_input_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask);
+
+EAPI Ecore_X_Pixmap   ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep);
+EAPI void             ecore_x_pixmap_free(Ecore_X_Pixmap pmap);
+EAPI void             ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, Ecore_X_Drawable dest, Ecore_X_GC gc, int sx, int sy, int w, int h, int dx, int dy);
+EAPI void             ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h);
+EAPI int              ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap);
+
+EAPI Ecore_X_GC       ecore_x_gc_new(Ecore_X_Drawable draw, Ecore_X_GC_Value_Mask value_mask, const unsigned int *value_list);
+EAPI void             ecore_x_gc_free(Ecore_X_GC gc);
+
+EAPI int              ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Event_Mask mask, long d0, long d1, long d2, long d3, long d4);
+EAPI int              ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, const void *data, int len);
+EAPI int              ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y);
+EAPI int              ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b);
+EAPI int              ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b);
+
+EAPI void            ecore_x_drawable_geometry_get_prefetch(Ecore_X_Drawable drawable);
+EAPI void            ecore_x_drawable_geometry_get_fetch(void);
+EAPI void            ecore_x_drawable_geometry_get(Ecore_X_Drawable d, int *x, int *y, int *w, int *h);
+EAPI int             ecore_x_drawable_border_width_get(Ecore_X_Drawable d);
+EAPI int             ecore_x_drawable_depth_get(Ecore_X_Drawable d);
+EAPI void            ecore_x_drawable_rectangle_fill(Ecore_X_Drawable d, Ecore_X_GC gc, int x, int y, int width, int height);
+
+EAPI int  ecore_x_cursor_color_supported_get(void);
+EAPI Ecore_X_Cursor ecore_x_cursor_new(Ecore_X_Window win, int *pixels, int w, int h, int hot_x, int hot_y);
+EAPI void ecore_x_cursor_free(Ecore_X_Cursor c);
+EAPI Ecore_X_Cursor ecore_x_cursor_shape_get(int shape);
+EAPI void ecore_x_cursor_size_set(int size);
+EAPI int  ecore_x_cursor_size_get(void);
+
+
+/* FIXME: these funcs need categorising */
+EAPI Ecore_X_Window *ecore_x_window_root_list(int *num_ret);
+EAPI Ecore_X_Window  ecore_x_window_root_first_get(void);
+EAPI int             ecore_x_window_manage(Ecore_X_Window win);
+EAPI void            ecore_x_window_container_manage(Ecore_X_Window win);
+EAPI void            ecore_x_window_client_manage(Ecore_X_Window win);
+EAPI void            ecore_x_window_sniff(Ecore_X_Window win);
+EAPI void            ecore_x_window_client_sniff(Ecore_X_Window win);
+EAPI void            ecore_x_atom_get_prefetch(const char *name);
+EAPI void            ecore_x_atom_get_fetch(void);
+EAPI Ecore_X_Atom    ecore_x_atom_get(const char *name);
+EAPI void            ecore_x_atoms_get(const char **names, int num, Ecore_X_Atom *atoms);
+EAPI void            ecore_x_get_atom_name_prefetch(Ecore_X_Atom atom);
+EAPI void            ecore_x_get_atom_name_fetch(void);
+EAPI char           *ecore_x_atom_name_get(Ecore_X_Atom atom);
+
+
+EAPI void            ecore_x_icccm_init(void);
+EAPI void            ecore_x_icccm_state_set(Ecore_X_Window win, Ecore_X_Window_State_Hint state);
+EAPI Ecore_X_Window_State_Hint ecore_x_icccm_state_get(Ecore_X_Window win);
+EAPI void            ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time t);
+EAPI void            ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time t);
+EAPI void            ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time t);
+EAPI void            ecore_x_icccm_move_resize_send(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI void  ecore_x_icccm_hints_set(Ecore_X_Window win,
+                                  int accepts_focus,
+                                  Ecore_X_Window_State_Hint initial_state,
+                                  Ecore_X_Pixmap icon_pixmap,
+                                  Ecore_X_Pixmap icon_mask,
+                                  Ecore_X_Window icon_window,
+                                  Ecore_X_Window window_group,
+                                  int is_urgent);
+EAPI int  ecore_x_icccm_hints_get(Ecore_X_Window win,
+                                 int *accepts_focus,
+                                 Ecore_X_Window_State_Hint *initial_state,
+                                 Ecore_X_Pixmap *icon_pixmap,
+                                 Ecore_X_Pixmap *icon_mask,
+                                 Ecore_X_Window *icon_window,
+                                 Ecore_X_Window *window_group,
+                                 int *is_urgent);
+EAPI void  ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win,
+                                           int request_pos,
+                                           Ecore_X_Gravity gravity,
+                                           int min_w, int min_h,
+                                           int max_w, int max_h,
+                                           int base_w, int base_h,
+                                           int step_x, int step_y,
+                                           double min_aspect,
+                                           double max_aspect);
+EAPI int   ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win,
+                                           int *request_pos,
+                                           Ecore_X_Gravity *gravity,
+                                           int *min_w, int *min_h,
+                                           int *max_w, int *max_h,
+                                           int *base_w, int *base_h,
+                                           int *step_x, int *step_y,
+                                           double *min_aspect,
+                                           double *max_aspect);
+EAPI void  ecore_x_icccm_title_set(Ecore_X_Window win, const char *t);
+EAPI char *ecore_x_icccm_title_get(Ecore_X_Window win);
+EAPI void  ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win,
+                                             Ecore_X_Atom *protos, int num);
+EAPI void  ecore_x_icccm_protocol_set(Ecore_X_Window win,
+                                     Ecore_X_WM_Protocol protocol,
+                                     int on);
+EAPI int   ecore_x_icccm_protocol_isset(Ecore_X_Window win,
+                                       Ecore_X_WM_Protocol protocol);
+EAPI void  ecore_x_icccm_name_class_set(Ecore_X_Window win,
+                                       const char *n,
+                                       const char *c);
+EAPI void  ecore_x_icccm_name_class_get(Ecore_X_Window win,
+                                       char **n,
+                                       char **c);
+EAPI char *ecore_x_icccm_client_machine_get(Ecore_X_Window win);
+EAPI void  ecore_x_icccm_command_set(Ecore_X_Window win, int argc, char **argv);
+EAPI void  ecore_x_icccm_command_get(Ecore_X_Window win, int *argc, char ***argv);
+EAPI char *ecore_x_icccm_icon_name_get(Ecore_X_Window win);
+EAPI void  ecore_x_icccm_icon_name_set(Ecore_X_Window win, const char *t);
+EAPI void  ecore_x_icccm_colormap_window_set(Ecore_X_Window win, Ecore_X_Window subwin);
+EAPI void  ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, Ecore_X_Window subwin);
+EAPI void  ecore_x_icccm_transient_for_set(Ecore_X_Window win, Ecore_X_Window forwin);
+EAPI void  ecore_x_icccm_transient_for_unset(Ecore_X_Window win);
+EAPI Ecore_X_Window ecore_x_icccm_transient_for_get(Ecore_X_Window win);
+EAPI void  ecore_x_icccm_window_role_set(Ecore_X_Window win, const char *role);
+EAPI char *ecore_x_icccm_window_role_get(Ecore_X_Window win);
+EAPI void  ecore_x_icccm_client_leader_set(Ecore_X_Window win, Ecore_X_Window l);
+EAPI Ecore_X_Window ecore_x_icccm_client_leader_get(Ecore_X_Window win);
+EAPI void ecore_x_icccm_iconic_request_send(Ecore_X_Window win, Ecore_X_Window root);
+
+
+typedef enum _Ecore_X_MWM_Hint_Func
+{
+   ECORE_X_MWM_HINT_FUNC_ALL = (1 << 0),
+   ECORE_X_MWM_HINT_FUNC_RESIZE = (1 << 1),
+   ECORE_X_MWM_HINT_FUNC_MOVE = (1 << 2),
+   ECORE_X_MWM_HINT_FUNC_MINIMIZE = (1 << 3),
+   ECORE_X_MWM_HINT_FUNC_MAXIMIZE = (1 << 4),
+   ECORE_X_MWM_HINT_FUNC_CLOSE = (1 << 5)
+} Ecore_X_MWM_Hint_Func;
+
+typedef enum _Ecore_X_MWM_Hint_Decor
+{
+   ECORE_X_MWM_HINT_DECOR_ALL = (1 << 0),
+   ECORE_X_MWM_HINT_DECOR_BORDER = (1 << 1),
+   ECORE_X_MWM_HINT_DECOR_RESIZEH = (1 << 2),
+   ECORE_X_MWM_HINT_DECOR_TITLE = (1 << 3),
+   ECORE_X_MWM_HINT_DECOR_MENU = (1 << 4),
+   ECORE_X_MWM_HINT_DECOR_MINIMIZE = (1 << 5),
+   ECORE_X_MWM_HINT_DECOR_MAXIMIZE = (1 << 6)
+} Ecore_X_MWM_Hint_Decor;
+
+typedef enum _Ecore_X_MWM_Hint_Input
+{
+   ECORE_X_MWM_HINT_INPUT_MODELESS = 0,
+   ECORE_X_MWM_HINT_INPUT_PRIMARY_APPLICATION_MODAL = 1,
+   ECORE_X_MWM_HINT_INPUT_SYSTEM_MODAL = 2,
+   ECORE_X_MWM_HINT_INPUT_FULL_APPLICATION_MODAL = 3
+} Ecore_X_MWM_Hint_Input;
+
+EAPI void ecore_x_mwm_hints_get_prefetch(Ecore_X_Window window);
+EAPI void ecore_x_mwm_hints_get_fetch(void);
+EAPI int  ecore_x_mwm_hints_get(Ecore_X_Window win,
+                                Ecore_X_MWM_Hint_Func *fhint,
+                                Ecore_X_MWM_Hint_Decor *dhint,
+                                Ecore_X_MWM_Hint_Input *ihint);
+EAPI void ecore_x_mwm_borderless_set(Ecore_X_Window win, int borderless);
+
+/* netwm */
+EAPI void                ecore_x_netwm_init(void);
+EAPI void                ecore_x_netwm_shutdown(void);
+EAPI void                ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check, const char *wm_name);
+EAPI void                ecore_x_netwm_supported_set(Ecore_X_Window root, Ecore_X_Atom *supported, int num);
+EAPI void                ecore_x_netwm_supported_get_prefetch(Ecore_X_Window root);
+EAPI void                ecore_x_netwm_supported_get_fetch(void);
+EAPI int                 ecore_x_netwm_supported_get(Ecore_X_Window root, Ecore_X_Atom **supported, int *num);
+EAPI void                ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks);
+EAPI void                ecore_x_netwm_desk_roots_set(Ecore_X_Window root, Ecore_X_Window *vroots, unsigned int n_desks);
+EAPI void                ecore_x_netwm_desk_names_set(Ecore_X_Window root, const char **names, unsigned int n_desks);
+EAPI void                ecore_x_netwm_desk_size_set(Ecore_X_Window root, unsigned int width, unsigned int height);
+EAPI void                ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, unsigned int *areas, unsigned int n_desks);
+EAPI void                ecore_x_netwm_desk_current_set(Ecore_X_Window root, unsigned int desk);
+EAPI void                ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, unsigned int *origins, unsigned int n_desks);
+EAPI void                ecore_x_netwm_desk_layout_set(Ecore_X_Window root, int orientation, int columns, int rows, int starting_corner);
+EAPI void                ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, int on);
+EAPI void                ecore_x_netwm_client_list_set(Ecore_X_Window root, Ecore_X_Window *p_clients, unsigned int n_clients);
+EAPI void                ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, Ecore_X_Window *p_clients, unsigned int n_clients);
+EAPI void                ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win);
+EAPI void                ecore_x_netwm_client_active_request(Ecore_X_Window root, Ecore_X_Window win, int type, Ecore_X_Window current_win);
+EAPI void                ecore_x_netwm_name_set(Ecore_X_Window win, const char *name);
+EAPI void                ecore_x_netwm_name_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_name_get_fetch(void);
+EAPI int                 ecore_x_netwm_name_get(Ecore_X_Window win, char **name);
+EAPI void                ecore_x_netwm_startup_id_set(Ecore_X_Window win, const char *id);
+EAPI void                ecore_x_netwm_startup_id_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_startup_id_get_fetch(void);
+EAPI int                 ecore_x_netwm_startup_id_get(Ecore_X_Window win, char **id);
+EAPI void                ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name);
+EAPI void                ecore_x_netwm_visible_name_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_visible_name_get_fetch(void);
+EAPI int                 ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name);
+EAPI void                ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name);
+EAPI void                ecore_x_netwm_icon_name_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_icon_name_get_fetch(void);
+EAPI int                 ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name);
+EAPI void                ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name);
+EAPI void                ecore_x_netwm_visible_icon_name_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_visible_icon_name_get_fetch(void);
+EAPI int                 ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name);
+EAPI void                ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk);
+EAPI void                ecore_x_netwm_desktop_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_desktop_get_fetch(void);
+EAPI int                 ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk);
+EAPI void                ecore_x_netwm_strut_set(Ecore_X_Window win, int left, int right, int top, int bottom);
+EAPI void                ecore_x_netwm_strut_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_strut_get_fetch(void);
+EAPI int                 ecore_x_netwm_strut_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom);
+EAPI void                ecore_x_netwm_strut_partial_set(Ecore_X_Window win, int left, int right, int top, int bottom, int left_start_y, int left_end_y, int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x);
+EAPI void                ecore_x_netwm_strut_partial_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_strut_partial_get_fetch(void);
+EAPI int                 ecore_x_netwm_strut_partial_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom, int *left_start_y, int *left_end_y, int *right_start_y, int *right_end_y, int *top_start_x, int *top_end_x, int *bottom_start_x, int *bottom_end_x);
+EAPI void                ecore_x_netwm_icons_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_icons_get_fetch(void);
+EAPI int                 ecore_x_netwm_icons_get(Ecore_X_Window win, Ecore_X_Icon **icon, int *num);
+EAPI void                ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height);
+EAPI void                ecore_x_netwm_icon_geometry_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_icon_geometry_get_fetch(void);
+EAPI int                 ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, int *x, int *y, int *width, int *height);
+EAPI void                ecore_x_netwm_pid_set(Ecore_X_Window win, int pid);
+EAPI void                ecore_x_netwm_pid_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_pid_get_fetch(void);
+EAPI int                 ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid);
+EAPI void                ecore_x_netwm_handled_icons_set(Ecore_X_Window win);
+EAPI void                ecore_x_netwm_handled_icons_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_handled_icons_get_fetch(void);
+EAPI int                 ecore_x_netwm_handled_icons_get(Ecore_X_Window win);
+EAPI void                ecore_x_netwm_user_time_set(Ecore_X_Window win, unsigned int time);
+EAPI void                ecore_x_netwm_user_time_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_user_time_get_fetch(void);
+EAPI int                 ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *time);
+EAPI void                ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State *state, unsigned int num);
+EAPI void                ecore_x_netwm_window_state_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_window_state_get_fetch(void);
+EAPI int                 ecore_x_netwm_window_state_get(Ecore_X_Window win, Ecore_X_Window_State **state, unsigned int *num);
+EAPI void                ecore_x_netwm_window_type_set(Ecore_X_Window win, Ecore_X_Window_Type type);
+EAPI void                ecore_x_netwm_window_type_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_window_type_get_fetch(void);
+EAPI int                 ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type);
+EAPI int                 ecore_x_netwm_window_types_get(Ecore_X_Window win, Ecore_X_Window_Type **types);
+EAPI int                 ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, Ecore_X_Action action);
+EAPI void                ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action *action, unsigned int num);
+EAPI void                ecore_x_netwm_allowed_action_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_allowed_action_get_fetch(void);
+EAPI int                 ecore_x_netwm_allowed_action_get(Ecore_X_Window win, Ecore_X_Action **action, unsigned int *num);
+EAPI void                ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity);
+EAPI void                ecore_x_netwm_opacity_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_opacity_get_fetch(void);
+EAPI int                 ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity);
+EAPI void                ecore_x_netwm_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb);
+EAPI void                ecore_x_netwm_frame_size_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_frame_size_get_fetch(void);
+EAPI int                 ecore_x_netwm_frame_size_get(Ecore_X_Window win, int *fl, int *fr, int *ft, int *fb);
+EAPI void                ecore_x_netwm_sync_counter_get_prefetch(Ecore_X_Window window);
+EAPI void                ecore_x_netwm_sync_counter_get_fetch(void);
+EAPI int                 ecore_x_netwm_sync_counter_get(Ecore_X_Window win, Ecore_X_Sync_Counter *counter);
+EAPI void                ecore_x_netwm_ping_send(Ecore_X_Window win);
+EAPI void                ecore_x_netwm_sync_request_send(Ecore_X_Window win, unsigned int serial);
+EAPI void                ecore_x_netwm_state_request_send(Ecore_X_Window win, Ecore_X_Window root, Ecore_X_Window_State s1, Ecore_X_Window_State s2, int set);
+EAPI void                ecore_x_netwm_desktop_request_send(Ecore_X_Window win, Ecore_X_Window root, unsigned int desktop);
+
+
+EAPI void                ecore_x_e_init(void);
+EAPI void                ecore_x_e_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb);
+EAPI void                ecore_x_e_virtual_keyboard_set(Ecore_X_Window win, unsigned int is_keyboard);
+EAPI int                 ecore_x_e_virtual_keyboard_get(Ecore_X_Window win);
+EAPI void                ecore_x_e_virtual_keyboard_state_set(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state);
+EAPI Ecore_X_Virtual_Keyboard_State ecore_x_e_virtual_keyboard_state_get(Ecore_X_Window win);
+EAPI void                ecore_x_e_virtual_keyboard_state_send(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state);
+
+
+/* Illume functions */
+EAPI void ecore_x_e_illume_zone_set(Ecore_X_Window win, Ecore_X_Window zone);
+EAPI Ecore_X_Window ecore_x_e_illume_zone_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_zone_list_set(Ecore_X_Window win, Ecore_X_Window *zones, unsigned int n_zones);
+EAPI void ecore_x_e_illume_conformant_set(Ecore_X_Window win, unsigned int is_conformant);
+EAPI int ecore_x_e_illume_conformant_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_mode_set(Ecore_X_Window win, Ecore_X_Illume_Mode mode);
+EAPI Ecore_X_Illume_Mode ecore_x_e_illume_mode_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_mode_send(Ecore_X_Window win, Ecore_X_Illume_Mode mode);
+EAPI void ecore_x_e_illume_focus_back_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_focus_forward_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_focus_home_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_close_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_home_new_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_home_del_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_drag_set(Ecore_X_Window win, unsigned int drag);
+EAPI int ecore_x_e_illume_drag_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_drag_locked_set(Ecore_X_Window win, unsigned int is_locked);
+EAPI int ecore_x_e_illume_drag_locked_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_drag_start_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_drag_end_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_indicator_geometry_set(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI int ecore_x_e_illume_indicator_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h);
+EAPI void ecore_x_e_illume_softkey_geometry_set(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI int ecore_x_e_illume_softkey_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h);
+EAPI void ecore_x_e_illume_keyboard_geometry_set(Ecore_X_Window win, int x, int y, int w, int h);
+EAPI int ecore_x_e_illume_keyboard_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h);
+EAPI void ecore_x_e_illume_quickpanel_set(Ecore_X_Window win, unsigned int is_quickpanel);
+EAPI int ecore_x_e_illume_quickpanel_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_state_set(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state);
+EAPI Ecore_X_Illume_Quickpanel_State ecore_x_e_illume_quickpanel_state_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_state_send(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state);
+EAPI void ecore_x_e_illume_quickpanel_state_toggle(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_priority_major_set(Ecore_X_Window win, unsigned int priority);
+EAPI int ecore_x_e_illume_quickpanel_priority_major_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_priority_minor_set(Ecore_X_Window win, unsigned int priority);
+EAPI int ecore_x_e_illume_quickpanel_priority_minor_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_zone_set(Ecore_X_Window win, unsigned int zone);
+EAPI int ecore_x_e_illume_quickpanel_zone_get(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_zone_request_send(Ecore_X_Window win);
+EAPI void ecore_x_e_illume_quickpanel_position_update_send(Ecore_X_Window win);
+
+EAPI void                 ecore_x_e_comp_sync_counter_set(Ecore_X_Window win, Ecore_X_Sync_Counter counter);
+EAPI Ecore_X_Sync_Counter ecore_x_e_comp_sync_counter_get(Ecore_X_Window win);
+EAPI void                 ecore_x_e_comp_sync_draw_done_send(Ecore_X_Window root, Ecore_X_Window win);
+EAPI void                 ecore_x_e_comp_sync_supported_set(Ecore_X_Window root, Eina_Bool enabled);
+EAPI Eina_Bool            ecore_x_e_comp_sync_supported_get(Ecore_X_Window root);
+EAPI void                 ecore_x_e_comp_sync_begin_send(Ecore_X_Window win);
+EAPI void                 ecore_x_e_comp_sync_end_send(Ecore_X_Window win);
+EAPI void                 ecore_x_e_comp_sync_cancel_send(Ecore_X_Window win);
+
+EAPI void                 ecore_x_e_comp_flush_send(Ecore_X_Window win);
+EAPI void                 ecore_x_e_comp_dump_send(Ecore_X_Window win);
+       
+EAPI Ecore_X_Sync_Alarm   ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter);
+EAPI int                  ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm);
+EAPI int                  ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, unsigned int *val);
+EAPI Ecore_X_Sync_Counter ecore_x_sync_counter_new(int val);
+EAPI void                 ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter);
+EAPI void                 ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, int by);
+EAPI void                 ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, int val);
+       
+EAPI void                ecore_x_xinerama_query_screens_prefetch(void);
+EAPI void                ecore_x_xinerama_query_screens_fetch(void);
+EAPI int                 ecore_x_xinerama_screen_count_get(void);
+EAPI int                 ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h);
+
+EAPI int                 ecore_x_screensaver_event_available_get(void);
+EAPI void                ecore_x_screensaver_idle_time_prefetch(void);
+EAPI void                ecore_x_screensaver_idle_time_fetch(void);
+EAPI int                 ecore_x_screensaver_idle_time_get(void);
+EAPI void                ecore_x_get_screensaver_prefetch(void);
+EAPI void                ecore_x_get_screensaver_fetch(void);
+EAPI void                ecore_x_screensaver_set(int timeout, int interval, int prefer_blanking, int allow_exposures);
+EAPI void                ecore_x_screensaver_timeout_set(int timeout);
+EAPI int                 ecore_x_screensaver_timeout_get(void);
+EAPI void                ecore_x_screensaver_blank_set(int timeout);
+EAPI int                 ecore_x_screensaver_blank_get(void);
+EAPI void                ecore_x_screensaver_expose_set(int timeout);
+EAPI int                 ecore_x_screensaver_expose_get(void);
+EAPI void                ecore_x_screensaver_interval_set(int timeout);
+EAPI int                 ecore_x_screensaver_interval_get(void);
+EAPI void                ecore_x_screensaver_event_listen_set(int on);
+
+/* FIXME: these funcs need categorising */
+
+typedef struct _Ecore_X_Window_Attributes
+{
+   Ecore_X_Window     root;
+   int                x, y, w, h;
+   int                border;
+   int                depth;
+   unsigned char      visible : 1;
+   unsigned char      viewable : 1;
+   unsigned char      override : 1;
+   unsigned char      input_only : 1;
+   unsigned char      save_under : 1;
+   struct {
+      Ecore_X_Event_Mask mine;
+      Ecore_X_Event_Mask all;
+      Ecore_X_Event_Mask no_propagate;
+   } event_mask;
+   Ecore_X_Gravity    window_gravity;
+   Ecore_X_Gravity    pixel_gravity;
+   Ecore_X_Colormap   colormap;
+   Ecore_X_Visual     visual;
+   /* FIXME: missing
+    * int map_installed;
+    * Screen *screen;
+    */
+} Ecore_X_Window_Attributes;
+   
+EAPI void ecore_x_get_window_attributes_prefetch(Ecore_X_Window window);
+EAPI void ecore_x_get_window_attributes_fetch(void);
+EAPI int  ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret);
+EAPI void ecore_x_window_save_set_add(Ecore_X_Window win);
+EAPI void ecore_x_window_save_set_del(Ecore_X_Window win);
+EAPI Ecore_X_Window *ecore_x_window_children_get(Ecore_X_Window win, int *num);
+
+EAPI int  ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold);
+EAPI void ecore_x_pointer_control_get_prefetch(void);
+EAPI void ecore_x_pointer_control_get_fetch(void);
+EAPI int  ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold);
+EAPI int  ecore_x_pointer_mapping_set(unsigned char *map, int nmap);
+EAPI void ecore_x_pointer_mapping_get_prefetch(void);
+EAPI void ecore_x_pointer_mapping_get_fetch(void);
+EAPI int  ecore_x_pointer_mapping_get(unsigned char *map, int nmap);
+EAPI int  ecore_x_pointer_grab(Ecore_X_Window win);
+EAPI int  ecore_x_pointer_confine_grab(Ecore_X_Window win);
+EAPI void ecore_x_pointer_ungrab(void);
+EAPI int  ecore_x_pointer_warp(Ecore_X_Window win, int x, int y);
+EAPI int  ecore_x_keyboard_grab(Ecore_X_Window win);
+EAPI void ecore_x_keyboard_ungrab(void);
+EAPI void ecore_x_grab(void);
+EAPI void ecore_x_ungrab(void);
+EAPI void ecore_x_passive_grab_replay_func_set(int (*func) (void *data, int event_type, void *event), void *data);
+EAPI void ecore_x_window_button_grab(Ecore_X_Window win, int button,
+                                    Ecore_X_Event_Mask event_mask,
+                                    int mod, int any_mod);
+EAPI void ecore_x_window_button_ungrab(Ecore_X_Window win, int button,
+                                      int mod, int any_mod);
+EAPI void ecore_x_window_key_grab(Ecore_X_Window win, const char *key,
+                                 int mod, int any_mod);
+EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key,
+                                   int mod, int any_mod);
+
+EAPI void ecore_x_focus_reset(void);
+EAPI void ecore_x_events_allow_all(void);
+EAPI void ecore_x_pointer_last_xy_get(int *x, int *y);
+EAPI void ecore_x_pointer_xy_get_prefetch(Ecore_X_Window window);
+EAPI void ecore_x_pointer_xy_get_fetch(void);
+EAPI void ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y);
+
+/* ecore_x_region.c */
+EAPI Ecore_X_XRegion *ecore_x_xregion_new();
+EAPI void             ecore_x_xregion_free(Ecore_X_XRegion *region);
+EAPI int              ecore_x_xregion_set(Ecore_X_XRegion *region, Ecore_X_GC gc);
+EAPI void             ecore_x_xregion_translate(Ecore_X_XRegion *region, int x, int y);
+EAPI int              ecore_x_xregion_intersect(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2);
+EAPI int              ecore_x_xregion_union(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2);
+EAPI int              ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, Ecore_X_XRegion *src, Ecore_X_Rectangle *rect);
+EAPI int              ecore_x_xregion_subtract(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2);
+EAPI int              ecore_x_xregion_is_empty(Ecore_X_XRegion *region);
+EAPI int              ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, Ecore_X_XRegion *r2);
+EAPI int              ecore_x_xregion_point_contain(Ecore_X_XRegion *region, int x, int y);
+EAPI int              ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, Ecore_X_Rectangle *rect);
+
+/* ecore_x_randr.c */
+typedef struct _Ecore_X_Screen_Size Ecore_X_Screen_Size;
+struct _Ecore_X_Screen_Size
+{
+   int width, height;
+};
+
+typedef struct _Ecore_X_Screen_Refresh_Rate Ecore_X_Screen_Refresh_Rate;
+struct _Ecore_X_Screen_Refresh_Rate
+{
+   int rate;
+};
+
+EAPI int                     ecore_x_randr_query(void);
+EAPI int                     ecore_x_randr_events_select(Ecore_X_Window win, int on);
+EAPI void                    ecore_x_randr_get_screen_info_prefetch(Ecore_X_Window window);
+EAPI void                    ecore_x_randr_get_screen_info_fetch(void);
+EAPI Ecore_X_Randr_Rotation  ecore_x_randr_screen_rotations_get(Ecore_X_Window root);
+EAPI Ecore_X_Randr_Rotation  ecore_x_randr_screen_rotation_get(Ecore_X_Window root);
+EAPI void                    ecore_x_randr_screen_rotation_set(Ecore_X_Window root, Ecore_X_Randr_Rotation rot);
+EAPI Ecore_X_Screen_Size    *ecore_x_randr_screen_sizes_get(Ecore_X_Window root, int *num);
+EAPI Ecore_X_Screen_Size     ecore_x_randr_current_screen_size_get(Ecore_X_Window root);
+EAPI int                     ecore_x_randr_screen_size_set(Ecore_X_Window root, Ecore_X_Screen_Size size);
+
+EAPI Ecore_X_Screen_Refresh_Rate *ecore_x_randr_screen_refresh_rates_get(Ecore_X_Window root, int size_id, int *num);
+EAPI Ecore_X_Screen_Refresh_Rate  ecore_x_randr_current_screen_refresh_rate_get(Ecore_X_Window root);
+
+EAPI int ecore_x_randr_screen_refresh_rate_set(Ecore_X_Window root, Ecore_X_Screen_Size size, Ecore_X_Screen_Refresh_Rate rate);
+
+/* XRender Support (horrendously incomplete) */
+typedef Ecore_X_ID  Ecore_X_Picture;
+
+/* XFixes Extension Support */
+typedef Ecore_X_ID  Ecore_X_Region;
+
+typedef enum _Ecore_X_Region_Type {
+     ECORE_X_REGION_BOUNDING,
+     ECORE_X_REGION_CLIP
+} Ecore_X_Region_Type;
+
+EAPI Ecore_X_Region ecore_x_region_new(Ecore_X_Rectangle *rects, int num);
+EAPI Ecore_X_Region ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap);
+EAPI Ecore_X_Region ecore_x_region_new_from_window(Ecore_X_Window win, Ecore_X_Region_Type type);
+EAPI Ecore_X_Region ecore_x_region_new_from_gc(Ecore_X_GC gc);
+EAPI Ecore_X_Region ecore_x_region_new_from_picture(Ecore_X_Picture picture);
+EAPI void           ecore_x_region_free(Ecore_X_Region region);
+EAPI void           ecore_x_region_set(Ecore_X_Region region, Ecore_X_Rectangle *rects, int num);
+EAPI void           ecore_x_region_copy(Ecore_X_Region dest, Ecore_X_Region source);
+EAPI void           ecore_x_region_combine(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2);
+EAPI void           ecore_x_region_intersect(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2);
+EAPI void           ecore_x_region_subtract(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2);
+EAPI void           ecore_x_region_invert(Ecore_X_Region dest, Ecore_X_Rectangle *bounds, Ecore_X_Region source);
+EAPI void           ecore_x_region_translate(Ecore_X_Region region, int dx, int dy);
+EAPI void           ecore_x_region_extents(Ecore_X_Region dest, Ecore_X_Region source);
+EAPI void           ecore_x_region_fetch_prefetch(Ecore_X_Region region);
+EAPI void           ecore_x_region_fetch_fetch(void);
+EAPI Ecore_X_Rectangle *ecore_x_region_fetch(Ecore_X_Region region, int *num, Ecore_X_Rectangle *bounds);
+EAPI void           ecore_x_region_expand(Ecore_X_Region dest, Ecore_X_Region source, unsigned int left, unsigned int right, unsigned int top, unsigned int bottom);
+EAPI void           ecore_x_region_gc_clip_set(Ecore_X_Region region, Ecore_X_GC gc, int x_origin, int y_origin);
+EAPI void           ecore_x_region_window_shape_set(Ecore_X_Region region, Ecore_X_Window win, Ecore_X_Shape_Type type, int x_offset, int y_offset);
+EAPI void           ecore_x_region_picture_clip_set(Ecore_X_Region region, Ecore_X_Picture picture, int x_origin, int y_origin);
+
+/* XComposite Extension Support */
+EAPI int               ecore_x_composite_query(void);
+EAPI void              ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
+EAPI void              ecore_x_composite_redirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
+EAPI void              ecore_x_composite_unredirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
+EAPI void              ecore_x_composite_unredirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
+EAPI Ecore_X_Pixmap    ecore_x_composite_name_window_pixmap_get(Ecore_X_Window win);
+EAPI Ecore_X_Window    ecore_x_composite_render_window_enable(Ecore_X_Window root);
+EAPI void              ecore_x_composite_render_window_disable(Ecore_X_Window root);
+       
+/* XDamage Extension Support */
+typedef Ecore_X_ID  Ecore_X_Damage;
+
+typedef enum _Ecore_X_Damage_Report_Level {
+     ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES,
+     ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES,
+     ECORE_X_DAMAGE_REPORT_BOUNDING_BOX,
+     ECORE_X_DAMAGE_REPORT_NON_EMPTY
+} Ecore_X_Damage_Report_Level;
+
+struct _Ecore_X_Event_Damage {
+     Ecore_X_Damage_Report_Level level;
+     Ecore_X_Drawable drawable;
+     Ecore_X_Damage   damage;
+     int              more;
+     Ecore_X_Time     time;
+     Ecore_X_Rectangle area;
+     Ecore_X_Rectangle  geometry;
+};
+
+typedef struct _Ecore_X_Event_Damage  Ecore_X_Event_Damage;
+
+EAPI int               ecore_x_damage_query(void);
+EAPI Ecore_X_Damage    ecore_x_damage_new(Ecore_X_Drawable d, Ecore_X_Damage_Report_Level level);
+EAPI void              ecore_x_damage_free(Ecore_X_Damage damage);
+EAPI void              ecore_x_damage_subtract(Ecore_X_Damage damage, Ecore_X_Region repair, Ecore_X_Region parts);
+
+EAPI int               ecore_x_screen_is_composited(int screen);
+EAPI void              ecore_x_screen_is_composited_set(int screen, Ecore_X_Window win);
+       
+EAPI int               ecore_x_dpms_query(void);
+EAPI void              ecore_x_dpms_capable_get_prefetch(void);
+EAPI void              ecore_x_dpms_capable_get_fetch(void);
+EAPI int               ecore_x_dpms_capable_get(void);
+EAPI void              ecore_x_dpms_enable_get_prefetch(void);
+EAPI void              ecore_x_dpms_enable_get_fetch(void);
+EAPI int               ecore_x_dpms_enabled_get(void);
+EAPI void              ecore_x_dpms_enabled_set(int enabled);
+EAPI void              ecore_x_dpms_timeouts_get_prefetch(void);
+EAPI void              ecore_x_dpms_timeouts_get_fetch(void);
+EAPI void              ecore_x_dpms_timeouts_get(unsigned int *standby, unsigned int *suspend, unsigned int *off);
+EAPI int               ecore_x_dpms_timeouts_set(unsigned int standby, unsigned int suspend, unsigned int off);
+EAPI unsigned int      ecore_x_dpms_timeout_standby_get(void);
+EAPI unsigned int      ecore_x_dpms_timeout_suspend_get(void);
+EAPI unsigned int      ecore_x_dpms_timeout_off_get(void);
+EAPI void              ecore_x_dpms_timeout_standby_set(unsigned int new_timeout);
+EAPI void              ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout);
+EAPI void              ecore_x_dpms_timeout_off_set(unsigned int new_timeout);
+
+EAPI int ecore_x_test_fake_key_down(const char *key);
+EAPI int ecore_x_test_fake_key_up(const char *key);
+EAPI int ecore_x_test_fake_key_press(const char *key);
+EAPI const char *ecore_x_keysym_string_get(int keysym);
+
+typedef struct _Ecore_X_Image Ecore_X_Image;
+
+EAPI Ecore_X_Image    *ecore_x_image_new(int w, int h, Ecore_X_Visual vis, int depth);
+EAPI void              ecore_x_image_free(Ecore_X_Image *im);
+EAPI Eina_Bool         ecore_x_image_get(Ecore_X_Image *im, Ecore_X_Drawable draw, int x, int y, int sx, int sy, int w, int h);
+EAPI void              ecore_x_image_put(Ecore_X_Image *im, Ecore_X_Drawable draw, int x, int y, int sx, int sy, int w, int h);
+EAPI void             *ecore_x_image_data_get(Ecore_X_Image *im, int *bpl, int *rows, int *bpp);
+
+EAPI Eina_Bool         ecore_x_input_multi_select(Ecore_X_Window win);
+       
+#ifdef __cplusplus
+}
+#endif
+
+#include <Ecore_X_Atoms.h>
+#include <Ecore_X_Cursor.h>
+
+#endif
diff --git a/src/lib/ecore_x/Ecore_X_Atoms.h b/src/lib/ecore_x/Ecore_X_Atoms.h
new file mode 100644 (file)
index 0000000..02d9905
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#ifndef _ECORE_X_ATOMS_H
+#define _ECORE_X_ATOMS_H
+
+/**
+ * @file
+ * @brief Ecore X atoms
+ */
+
+/* generic atoms */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_ATOM;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_CARDINAL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_FILE_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_STRING;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEXT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WINDOW;
+
+/* dnd atoms */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_MOVE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LINK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_PROXY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_DROP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED;
+
+/* dnd atoms that need to be exposed to the application interface */
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_COPY;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_MOVE;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_LINK;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_ASK;
+EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE;
+/* old E atom */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE;
+
+/* old Gnome atom */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER;
+
+/* ICCCM: client properties */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_HINTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLASS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE;
+
+/* ICCCM: window manager properties */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_STATE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_ICON_SIZE;
+
+/* ICCCM: WM_STATEproperty */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE;
+
+/* ICCCM: WM_PROTOCOLS properties */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW;
+
+/* ICCCM: WM_COLORMAP properties */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_NOTIFY;
+
+/* ICCCM: session management properties */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SM_CLIENT_ID;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE;
+
+/* Motif WM atom */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS;
+
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP;
+
+/* pager */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_MOVERESIZE_WINDOW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_RESTACK_WINDOW;
+
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP;
+
+/* window type */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND;
+
+/* state */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
+
+/* allowed actions */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_BELOW;
+
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_ID;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADOW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
+
+/* currenly E specific virtual keyboard extension, aim to submit to netwm spec
+ * later */
+
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD;
+EAPI extern Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME;
+
+
+/* Illume specific atoms */
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE_LIST;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CONFORMANT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_SINGLE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_BACK;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_HOME;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_NEW;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_DEL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLOSE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_START;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_END;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE;
+
+
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_COUNTER;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_BEGIN;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_END;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_CANCEL;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_FLUSH;
+EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_DUMP;
+
+#endif /* _ECORE_X_ATOMS_H */
diff --git a/src/lib/ecore_x/Ecore_X_Cursor.h b/src/lib/ecore_x/Ecore_X_Cursor.h
new file mode 100644 (file)
index 0000000..af2e97a
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _ECORE_X_CURSOR_H
+#define _ECORE_X_CURSOR_H
+
+/**
+ * @file
+ * @brief Defines the various cursor types for the X Windows system.
+ */
+
+#define ECORE_X_CURSOR_X 0
+#define ECORE_X_CURSOR_ARROW 2
+#define ECORE_X_CURSOR_BASED_ARROW_DOWN 4
+#define ECORE_X_CURSOR_UP 6
+#define ECORE_X_CURSOR_BOAT 8
+#define ECORE_X_CURSOR_BOTTOM_LEFT_CORNER 12
+#define ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER 14
+#define ECORE_X_CURSOR_BOTTOM_SIDE 16
+#define ECORE_X_CURSOR_BOTTOM_TEE 18
+#define ECORE_X_CURSOR_BOX_SPIRAL 20
+#define ECORE_X_CURSOR_CENTER_PTR 22
+#define ECORE_X_CURSOR_CIRCLE 24
+#define ECORE_X_CURSOR_CLOCK 26
+#define ECORE_X_CURSOR_COFFEE_MUG 28
+#define ECORE_X_CURSOR_CROSS 30
+#define ECORE_X_CURSOR_CROSS_REVERSE 32
+#define ECORE_X_CURSOR_CROSSHAIR 34
+#define ECORE_X_CURSOR_DIAMOND_CROSS 36
+#define ECORE_X_CURSOR_DOT 38
+#define ECORE_X_CURSOR_DOT_BOX_MASK 40
+#define ECORE_X_CURSOR_DOUBLE_ARROW 42
+#define ECORE_X_CURSOR_DRAFT_LARGE 44
+#define ECORE_X_CURSOR_DRAFT_SMALL 46
+#define ECORE_X_CURSOR_DRAPED_BOX 48
+#define ECORE_X_CURSOR_EXCHANGE 50
+#define ECORE_X_CURSOR_FLEUR 52
+#define ECORE_X_CURSOR_GOBBLER 54
+#define ECORE_X_CURSOR_GUMBY 56
+#define ECORE_X_CURSOR_HAND1 58
+#define ECORE_X_CURSOR_HAND2 60
+#define ECORE_X_CURSOR_HEART 62
+#define ECORE_X_CURSOR_ICON 64
+#define ECORE_X_CURSOR_IRON_CROSS 66
+#define ECORE_X_CURSOR_LEFT_PTR 68
+#define ECORE_X_CURSOR_LEFT_SIDE 70
+#define ECORE_X_CURSOR_LEFT_TEE 72
+#define ECORE_X_CURSOR_LEFTBUTTON 74
+#define ECORE_X_CURSOR_LL_ANGLE 76
+#define ECORE_X_CURSOR_LR_ANGLE 78
+#define ECORE_X_CURSOR_MAN 80
+#define ECORE_X_CURSOR_MIDDLEBUTTON 82
+#define ECORE_X_CURSOR_MOUSE 84
+#define ECORE_X_CURSOR_PENCIL 86
+#define ECORE_X_CURSOR_PIRATE 88
+#define ECORE_X_CURSOR_PLUS 90
+#define ECORE_X_CURSOR_QUESTION_ARROW 92
+#define ECORE_X_CURSOR_RIGHT_PTR 94
+#define ECORE_X_CURSOR_RIGHT_SIDE 96
+#define ECORE_X_CURSOR_RIGHT_TEE 98
+#define ECORE_X_CURSOR_RIGHTBUTTON 100
+#define ECORE_X_CURSOR_RTL_LOGO 102
+#define ECORE_X_CURSOR_SAILBOAT 104
+#define ECORE_X_CURSOR_SB_DOWN_ARROW 106
+#define ECORE_X_CURSOR_SB_H_DOUBLE_ARROW 108
+#define ECORE_X_CURSOR_SB_LEFT_ARROW 110
+#define ECORE_X_CURSOR_SB_RIGHT_ARROW 112
+#define ECORE_X_CURSOR_SB_UP_ARROW 114
+#define ECORE_X_CURSOR_SB_V_DOUBLE_ARROW 116
+#define ECORE_X_CURSOR_SHUTTLE 118
+#define ECORE_X_CURSOR_SIZING 120
+#define ECORE_X_CURSOR_SPIDER 122
+#define ECORE_X_CURSOR_SPRAYCAN 124
+#define ECORE_X_CURSOR_STAR 126
+#define ECORE_X_CURSOR_TARGET 128
+#define ECORE_X_CURSOR_TCROSS 130
+#define ECORE_X_CURSOR_TOP_LEFT_ARROW 132
+#define ECORE_X_CURSOR_TOP_LEFT_CORNER 134
+#define ECORE_X_CURSOR_TOP_RIGHT_CORNER 136
+#define ECORE_X_CURSOR_TOP_SIDE 138
+#define ECORE_X_CURSOR_TOP_TEE 140
+#define ECORE_X_CURSOR_TREK 142
+#define ECORE_X_CURSOR_UL_ANGLE 144
+#define ECORE_X_CURSOR_UMBRELLA 146
+#define ECORE_X_CURSOR_UR_ANGLE 148
+#define ECORE_X_CURSOR_WATCH 150
+#define ECORE_X_CURSOR_XTERM 152
+
+#endif
diff --git a/src/lib/ecore_x/Makefile.am b/src/lib/ecore_x/Makefile.am
new file mode 100644 (file)
index 0000000..1286b37
--- /dev/null
@@ -0,0 +1,33 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_X
+
+SUBDIRS = xlib xcb
+
+if BUILD_ECORE_X_XCB
+DEP = xcb/libecore_x_xcb.la
+else
+DEP = xlib/libecore_x_xlib.la
+endif
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore \
+@EINA_CFLAGS@
+
+lib_LTLIBRARIES = libecore_x.la
+
+libecore_x_la_SOURCES =
+
+libecore_x_la_LIBADD = $(DEP) @EINA_LIBS@
+libecore_x_la_LDFLAGS = -version-info @version_info@ @ecore_x_release_info@
+libecore_x_la_DEPENDENCIES = $(DEP)
+
+include_HEADERS = \
+Ecore_X.h \
+Ecore_X_Atoms.h \
+Ecore_X_Cursor.h
+
+endif
+
+EXTRA_DIST = ecore_x_atoms_decl.h
diff --git a/src/lib/ecore_x/ecore_x_atoms_decl.h b/src/lib/ecore_x/ecore_x_atoms_decl.h
new file mode 100644 (file)
index 0000000..fd7e9b6
--- /dev/null
@@ -0,0 +1,275 @@
+/* generic atoms */
+EAPI Ecore_X_Atom ECORE_X_ATOM_ATOM                     = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_CARDINAL                 = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT            = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_FILE_NAME                = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_STRING                   = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_TEXT                     = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING              = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_WINDOW                   = 0;
+
+/* dnd atoms */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_PROP_XDND     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_XDND          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_AWARE              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ENTER              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_TYPE_LIST          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_POSITION           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_COPY        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_MOVE        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_PRIVATE     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_ASK         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_LIST        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_LINK        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_PROXY              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_STATUS             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_LEAVE              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_DROP               = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_XDND_FINISHED           = 0;
+
+/* dnd atoms that need to be exposed to the application interface */
+EAPI Ecore_X_Atom  ECORE_X_DND_ACTION_COPY              = 0;
+EAPI Ecore_X_Atom  ECORE_X_DND_ACTION_MOVE              = 0;
+EAPI Ecore_X_Atom  ECORE_X_DND_ACTION_LINK              = 0;
+EAPI Ecore_X_Atom  ECORE_X_DND_ACTION_ASK               = 0;
+EAPI Ecore_X_Atom  ECORE_X_DND_ACTION_PRIVATE           = 0;
+
+/* old E atom */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_FRAME_SIZE            = 0;
+
+/* old Gnome atom */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WIN_LAYER               = 0;
+
+/* ICCCM atoms */
+
+/* ICCCM: client properties */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_NAME                 = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_ICON_NAME            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_NORMAL_HINTS         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_SIZE_HINTS           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_HINTS                = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_CLASS                = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_TRANSIENT_FOR        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_PROTOCOLS            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_COLORMAP_WINDOWS     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_COMMAND              = 0; /* obsolete */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_CLIENT_MACHINE       = 0; /* obsolete */
+
+/* ICCCM: window manager properties */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_STATE                = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_ICON_SIZE            = 0;
+
+/* ICCCM: WM_STATE  property */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_CHANGE_STATE         = 0;
+
+/* ICCCM: WM_PROTOCOLS properties */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_TAKE_FOCUS           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_SAVE_YOURSELF        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_DELETE_WINDOW        = 0;
+
+/* ICCCM: WM_COLORMAP properties */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_COLORMAP_NOTIFY      = 0;
+
+/* ICCCM: session management properties */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SM_CLIENT_ID            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_CLIENT_LEADER        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_WM_WINDOW_ROLE          = 0;
+
+/* Motif WM atom */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_MOTIF_WM_HINTS          = 0;
+
+/* NetWM 1.3 atoms (http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html) */
+
+/*
+ * NetWM: Root Window Properties and related messages (complete)
+ */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_SUPPORTED                  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_CLIENT_LIST                = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_CLIENT_LIST_STACKING       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_DESKTOP_GEOMETRY           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_DESKTOP_VIEWPORT           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_CURRENT_DESKTOP            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_DESKTOP_NAMES              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_ACTIVE_WINDOW              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WORKAREA                   = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_VIRTUAL_ROOTS              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_DESKTOP_LAYOUT             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_SHOWING_DESKTOP            = 0;
+
+/*
+ * NetWM: Other Root Window Messages (complete)
+ */
+
+/* pager */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_CLOSE_WINDOW               = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_MOVERESIZE_WINDOW          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_MOVERESIZE              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_RESTACK_WINDOW             = 0;
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS      = 0;
+
+/*
+ * NetWM: Application Window Properties (complete)
+ */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_NAME                    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_VISIBLE_NAME            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ICON_NAME               = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_DESKTOP                 = 0;
+
+/* window type */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE               = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND           = 0;
+
+/* state */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE                   = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_MODAL             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_STICKY            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_SHADED            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR      = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_HIDDEN            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_ABOVE             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_BELOW             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = 0;
+
+/* allowed actions */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_MOVE             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_RESIZE           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_SHADE            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_STICK            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP   = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_CLOSE            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_ABOVE            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ACTION_BELOW            = 0;
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STRUT                   = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_STRUT_PARTIAL           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ICON_GEOMETRY           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_ICON                    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_PID                     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_HANDLED_ICONS           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_USER_TIME               = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_STARTUP_ID                 = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_FRAME_EXTENTS              = 0;
+
+/*
+ * NetWM: Window Manager Protocols (complete)
+ */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_PING                    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_SYNC_REQUEST            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER    = 0;
+
+/*
+ * NetWM: Not in the spec
+ */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_OPACITY          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_SHADOW           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_WM_WINDOW_SHADE            = 0;
+
+/*
+ * Startup Notification (http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt)
+ */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_NET_STARTUP_INFO               = 0;
+
+/* selection atoms */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_TARGETS              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_PRIMARY              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_SECONDARY            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_CLIPBOARD            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_PROP_PRIMARY         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_PROP_SECONDARY       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD       = 0;
+
+/* currently E specific virtual keyboard extension, aim to submit to netwm spec
+ * later */
+
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER= 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP          = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD      = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME        = 0;
+
+/* currently E specific illume extension */
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_ZONE                  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_ZONE_LIST             = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_CONFORMANT            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_MODE                  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_MODE_SINGLE           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_FOCUS_BACK            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_FOCUS_HOME            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_CLOSE                 = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_HOME_NEW              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_HOME_DEL              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_DRAG                  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED           = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_DRAG_START            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_DRAG_END              = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY      = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY     = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL            = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE      = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE    = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON         = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF        = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR  = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE       = 0;
+EAPI Ecore_X_Atom  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE = 0;
+
+
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_COUNTER = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_BEGIN = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_END = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_CANCEL = 0;
+
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_FLUSH = 0;
+EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_DUMP = 0;
diff --git a/src/lib/ecore_x/xcb/.cvsignore b/src/lib/ecore_x/xcb/.cvsignore
new file mode 100644 (file)
index 0000000..5fba3e8
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_x_xcb.la
diff --git a/src/lib/ecore_x/xcb/Makefile.am b/src/lib/ecore_x/xcb/Makefile.am
new file mode 100644 (file)
index 0000000..81152ad
--- /dev/null
@@ -0,0 +1,82 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_X_XCB
+
+AM_CPPFLAGS = \
+@XCB_DAMAGE_CFLAGS@ \
+@XCB_COMPOSITE_CFLAGS@ \
+@XCB_DPMS_CFLAGS@ \
+@XCB_RANDR_CFLAGS@ \
+@XCB_RENDER_CFLAGS@ \
+@XCB_SCREENSAVER_CFLAGS@ \
+@XCB_SHAPE_CFLAGS@ \
+@XCB_SYNC_CFLAGS@ \
+@XCB_XFIXES_CFLAGS@ \
+@XCB_XINERAMA_CFLAGS@ \
+@XCB_XPRINT_CFLAGS@ \
+@XCB_XTEST_CFLAGS@ \
+@XCB_CFLAGS@ \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_x \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_x \
+-I$(top_builddir)/src/lib/ecore_input \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+noinst_LTLIBRARIES = libecore_x_xcb.la
+
+libecore_x_xcb_la_SOURCES = \
+ecore_xcb_atom.c \
+ecore_xcb_cursor.c \
+ecore_xcb_damage.c \
+ecore_xcb_composite.c \
+ecore_xcb_dnd.c \
+ecore_xcb_dpms.c \
+ecore_xcb_drawable.c \
+ecore_xcb_e.c \
+ecore_xcb_events.c \
+ecore_xcb_fixes.c \
+ecore_xcb_gc.c \
+ecore_xcb_icccm.c \
+ecore_xcb_mwm.c \
+ecore_xcb_netwm.c \
+ecore_xcb_pixmap.c \
+ecore_xcb_randr.c \
+ecore_xcb_region.c \
+ecore_xcb_reply.c \
+ecore_xcb_screensaver.c \
+ecore_xcb_selection.c \
+ecore_xcb_shape.c \
+ecore_xcb_sync.c \
+ecore_xcb_window.c \
+ecore_xcb_window_prop.c \
+ecore_xcb_window_shadow.c \
+ecore_xcb_xinerama.c \
+ecore_xcb.c
+
+libecore_x_xcb_la_LIBADD = \
+@XCB_DAMAGE_LIBS@ \
+@XCB_COMPOSITE_LIBS@ \
+@XCB_DPMS_LIBS@ \
+@XCB_RANDR_LIBS@ \
+@XCB_RENDER_LIBS@ \
+@XCB_SCREENSAVER_LIBS@ \
+@XCB_SHAPE_LIBS@ \
+@XCB_SYNC_LIBS@ \
+@XCB_XFIXES_LIBS@ \
+@XCB_XINERAMA_LIBS@ \
+@XCB_XPRINT_LIBS@ \
+@XCB_XTEST_LIBS@ \
+@XCB_LIBS@ \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@EINA_LIBS@
+
+libecore_x_xcb_la_LDFLAGS = -version-info @version_info@
+
+endif
+
+EXTRA_DIST = ecore_xcb_private.h
diff --git a/src/lib/ecore_x/xcb/ecore_xcb.c b/src/lib/ecore_x/xcb/ecore_xcb.c
new file mode 100644 (file)
index 0000000..7f1a63e
--- /dev/null
@@ -0,0 +1,1975 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <string.h>
+
+#include <X11/keysym.h>
+
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+static int _ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_xcb_key_mask_get(xcb_keysym_t sym);
+static int _ecore_xcb_event_modifier(unsigned int state);
+
+static void *_ecore_xcb_event_filter_start(void *data);
+static int   _ecore_xcb_event_filter_filter(void *data, void *loop_data,int type, void *event);
+static void  _ecore_xcb_event_filter_end(void *data, void *loop_data);
+
+static Ecore_Fd_Handler *_ecore_xcb_fd_handler_handle = NULL;
+static Ecore_Event_Filter *_ecore_xcb_filter_handler = NULL;
+
+static const int XCB_EVENT_ANY = 0; /* 0 can be used as there are no event types
+                                     * with index 0 and 1 as they are used for
+                                     * errors
+                                     */
+
+#ifdef ECORE_XCB_DAMAGE
+static int _ecore_xcb_event_damage_id = 0;
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_RANDR
+static int _ecore_xcb_event_randr_id = 0;
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+static int _ecore_xcb_event_screensaver_id = 0;
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+static int _ecore_xcb_event_shape_id = 0;
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+static int _ecore_xcb_event_sync_id = 0;
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+static int _ecore_xcb_event_fixes_selection_id = 0;
+#endif /* ECORE_XCB_FIXES */
+
+static int _ecore_xcb_event_handlers_num = 0;
+static void (**_ecore_xcb_event_handlers) (xcb_generic_event_t * event) = NULL;
+static xcb_generic_event_t *_ecore_xcb_event_buffered = NULL;
+
+static int _ecore_xcb_init_count = 0;
+static int _ecore_xcb_grab_count = 0;
+int _ecore_x11xcb_log_dom = -1;
+
+Ecore_X_Connection *_ecore_xcb_conn = NULL;
+Ecore_X_Screen     *_ecore_xcb_screen = NULL;
+double              _ecore_xcb_double_click_time = 0.25;
+Ecore_X_Time        _ecore_xcb_event_last_time = XCB_NONE;
+Ecore_X_Window      _ecore_xcb_event_last_window = XCB_NONE;
+int16_t             _ecore_xcb_event_last_root_x = 0;
+int16_t             _ecore_xcb_event_last_root_y = 0;
+int                 _ecore_xcb_xcursor = 0;
+
+Ecore_X_Window      _ecore_xcb_private_window = 0;
+
+/* FIXME - These are duplicates after making ecore atoms public */
+
+Ecore_X_Atom        _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
+
+
+EAPI int ECORE_X_EVENT_ANY                      = 0;
+EAPI int ECORE_X_EVENT_MOUSE_IN                 = 0;
+EAPI int ECORE_X_EVENT_MOUSE_OUT                = 0;
+EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN          = 0;
+EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT         = 0;
+EAPI int ECORE_X_EVENT_WINDOW_KEYMAP            = 0;
+EAPI int ECORE_X_EVENT_WINDOW_DAMAGE            = 0;
+EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CREATE            = 0;
+EAPI int ECORE_X_EVENT_WINDOW_DESTROY           = 0;
+EAPI int ECORE_X_EVENT_WINDOW_HIDE              = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHOW              = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST      = 0;
+EAPI int ECORE_X_EVENT_WINDOW_REPARENT          = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE         = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_GRAVITY           = 0;
+EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST    = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STACK             = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST     = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROPERTY          = 0;
+EAPI int ECORE_X_EVENT_WINDOW_COLORMAP          = 0;
+EAPI int ECORE_X_EVENT_WINDOW_MAPPING           = 0;
+EAPI int ECORE_X_EVENT_SELECTION_CLEAR          = 0;
+EAPI int ECORE_X_EVENT_SELECTION_REQUEST        = 0;
+EAPI int ECORE_X_EVENT_SELECTION_NOTIFY         = 0;
+EAPI int ECORE_X_EVENT_CLIENT_MESSAGE           = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHAPE             = 0;
+EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY       = 0;
+EAPI int ECORE_X_EVENT_SYNC_COUNTER             = 0;
+EAPI int ECORE_X_EVENT_SYNC_ALARM               = 0;
+EAPI int ECORE_X_EVENT_SCREEN_CHANGE            = 0;
+EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY            = 0;
+
+EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST    = 0;
+/*
+EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0;
+*/
+
+EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST       = 0;
+EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST      = 0;
+EAPI int ECORE_X_EVENT_PING                       = 0;
+EAPI int ECORE_X_EVENT_DESKTOP_CHANGE             = 0;
+
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW       = 0;
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE    = 0;
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE    = 0;
+
+EAPI int ECORE_X_MODIFIER_SHIFT                   = 0;
+EAPI int ECORE_X_MODIFIER_CTRL                    = 0;
+EAPI int ECORE_X_MODIFIER_ALT                     = 0;
+EAPI int ECORE_X_MODIFIER_WIN                     = 0;
+
+EAPI int ECORE_X_LOCK_SCROLL                      = 0;
+EAPI int ECORE_X_LOCK_NUM                         = 0;
+EAPI int ECORE_X_LOCK_CAPS                        = 0;
+
+/**
+ * @defgroup Ecore_Xcb_Init_Group X Library Init and Shutdown Functions
+ *
+ * Functions that start and shut down the Ecore X Library.
+ */
+
+/**
+ * Initialize the X display connection to the given display.
+ *
+ * @param   name Display target name.  If @c NULL, the default display is
+ *               assumed.
+ * @return  The number of times the library has been initialized without
+ *          being shut down.  0 is returned if an error occurs.
+ * @ingroup Ecore_Xcb_Init_Group
+ */
+EAPI int
+ecore_x_init(const char *name)
+{
+   xcb_screen_iterator_t              iter;
+   int                                screen;
+   uint32_t                           max_request_length;
+   const xcb_query_extension_reply_t *reply_big_requests;
+#ifdef ECORE_XCB_DAMAGE
+   const xcb_query_extension_reply_t *reply_damage;
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_COMPOSITE
+   const xcb_query_extension_reply_t *reply_composite;
+#endif /* ECORE_XCB_COMPOSITE */
+#ifdef ECORE_XCB_DPMS
+   const xcb_query_extension_reply_t *reply_dpms;
+#endif /* ECORE_XCB_DPMS */
+#ifdef ECORE_XCB_RANDR
+   const xcb_query_extension_reply_t *reply_randr;
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+   const xcb_query_extension_reply_t *reply_screensaver;
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+   const xcb_query_extension_reply_t *reply_shape;
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+   xcb_sync_initialize_cookie_t       cookie_sync_init;
+   xcb_sync_initialize_reply_t       *reply_sync_init;
+   const xcb_query_extension_reply_t *reply_sync;
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+   const xcb_query_extension_reply_t *reply_xfixes;
+#endif /* ECORE_XCB_FIXES */
+#ifdef ECORE_XCB_XINERAMA
+   const xcb_query_extension_reply_t *reply_xinerama;
+#endif /* ECORE_XCB_XINERAMA */
+#ifdef ECORE_XCB_XPRINT
+   const xcb_query_extension_reply_t *reply_xprint;
+#endif /* ECORE_XCB_XPRINT */
+
+   xcb_intern_atom_cookie_t           atom_cookies[ECORE_X_ATOMS_COUNT];
+
+   if (++_ecore_xcb_init_count != 1)
+     return _ecore_xcb_init_count;
+   _ecore_x11xcb_log_dom = eina_log_domain_register("EcoreXCB", ECORE_XLIB_XCB_DEFAULT_LOG_COLOR);
+   if(_ecore_x11xcb_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain the Ecore XCB module.");
+       return --_ecore_xcb_init_count;
+     }
+   _ecore_xcb_conn = xcb_connect(name, &screen);
+   if (xcb_connection_has_error(_ecore_xcb_conn)) {
+     eina_log_domain_unregister(_ecore_x11xcb_log_dom);
+     _ecore_x11xcb_log_dom = -1;
+     return --_ecore_xcb_init_count;
+   }
+   /* FIXME: no error code right now */
+   /* _ecore_xcb_error_handler_init(); */
+
+   /********************/
+   /* First round trip */
+   /********************/
+
+   /*
+    * Non blocking stuff:
+    *
+    * 1. We request the atoms
+    * 2. We Prefetch the extension data
+    *
+    */
+
+
+   /* We request the atoms (non blocking) */
+   _ecore_x_atom_init(atom_cookies);
+
+   /* We prefetch all the extension data (non blocking) */
+
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_big_requests_id);
+
+#ifdef ECORE_XCB_DAMAGE
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_damage_id);
+#endif /* ECORE_XCB_DAMAGE */
+
+#ifdef ECORE_XCB_COMPOSITE
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_composite_id);
+#endif /* ECORE_XCB_COMPOSITE */
+
+#ifdef ECORE_XCB_DPMS
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_dpms_id);
+#endif /* ECORE_XCB_DPMS */
+
+#ifdef ECORE_XCB_RANDR
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_randr_id);
+#endif /* ECORE_XCB_RANDR */
+
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_screensaver_id);
+#endif /* ECORE_XCB_SCREENSAVER */
+
+#ifdef ECORE_XCB_SHAPE
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_shape_id);
+#endif /* ECORE_XCB_SHAPE */
+
+#ifdef ECORE_XCB_SYNC
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_sync_id);
+   cookie_sync_init = xcb_sync_initialize_unchecked(_ecore_xcb_conn,
+                                                    XCB_SYNC_MAJOR_VERSION,
+                                                    XCB_SYNC_MINOR_VERSION);
+#endif /* ECORE_XCB_SYNC */
+
+#ifdef ECORE_XCB_FIXES
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
+#endif /* ECORE_XCB_FIXES */
+
+#ifdef ECORE_XCB_XINERAMA
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xinerama_id);
+#endif /* ECORE_XCB_XINERAMA */
+
+#ifdef ECORE_XCB_XPRINT
+   xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_x_print_id);
+#endif /* ECORE_XCB_XPRINT */
+
+   /* We init some components (not related to XCB) */
+   if (!ecore_event_init())
+     goto close_connection;
+
+   _ecore_x_reply_init();
+   _ecore_x_dnd_init();
+   ecore_x_netwm_init();
+   _ecore_x_selection_init();
+
+   /* There is no LASTEvent constant in XCB */
+   /* LASTevent is equal to 35 */
+   _ecore_xcb_event_handlers_num = 35;
+
+   /* We get the default screen */
+   iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
+   for (; iter.rem; --screen, xcb_screen_next (&iter))
+     if (screen == 0)
+       {
+          _ecore_xcb_screen = iter.data;
+          break;
+       }
+
+   /*
+    * Blocking stuff:
+    *
+    * 1. We get the atoms
+    * 2. We ask for the extension data
+    *
+    */
+
+   /* We get the atoms (blocking) */
+   _ecore_x_atom_init_finalize(atom_cookies);
+
+   /* We then ask for the extension data (blocking) */
+   reply_big_requests = xcb_get_extension_data(_ecore_xcb_conn, &xcb_big_requests_id);
+
+#ifdef ECORE_XCB_DAMAGE
+   reply_damage = xcb_get_extension_data(_ecore_xcb_conn, &xcb_damage_id);
+   if (reply_damage)
+     _ecore_xcb_event_damage_id = reply_damage->first_event + XCB_DAMAGE_NOTIFY;
+   if (_ecore_xcb_event_damage_id >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_damage_id + 1;
+#endif /* ECORE_XCB_DAMAGE */
+
+#ifdef ECORE_XCB_COMPOSITE
+   reply_composite = xcb_get_extension_data(_ecore_xcb_conn, &xcb_composite_id);
+#endif /* ECORE_XCB_COMPOSITE */
+
+#ifdef ECORE_XCB_DPMS
+   reply_dpms = xcb_get_extension_data(_ecore_xcb_conn, &xcb_dpms_id);
+#endif /* ECORE_XCB_DPMS */
+
+#ifdef ECORE_XCB_RANDR
+   reply_randr = xcb_get_extension_data(_ecore_xcb_conn, &xcb_randr_id);
+   if (reply_randr)
+     _ecore_xcb_event_randr_id = reply_randr->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY;
+   if (_ecore_xcb_event_randr_id >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_randr_id + 1;
+#endif /* ECORE_XCB_RANDR */
+
+#ifdef ECORE_XCB_SCREENSAVER
+   reply_screensaver = xcb_get_extension_data(_ecore_xcb_conn, &xcb_screensaver_id);
+   if (reply_screensaver)
+     _ecore_xcb_event_screensaver_id = reply_screensaver->first_event + XCB_SCREENSAVER_NOTIFY;
+   if (_ecore_xcb_event_screensaver_id >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_screensaver_id + 1;
+#endif /* ECORE_XCB_SCREENSAVER */
+
+#ifdef ECORE_XCB_SHAPE
+   reply_shape = xcb_get_extension_data(_ecore_xcb_conn, &xcb_shape_id);
+   if (reply_shape)
+     _ecore_xcb_event_shape_id = reply_shape->first_event + XCB_SHAPE_NOTIFY;
+   if (_ecore_xcb_event_shape_id >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_shape_id + 1;
+#endif /* ECORE_XCB_SHAPE */
+
+#ifdef ECORE_XCB_SYNC
+   reply_sync = xcb_get_extension_data(_ecore_xcb_conn, &xcb_sync_id);
+   if (reply_sync)
+     {
+       _ecore_xcb_event_sync_id = reply_sync->first_event;
+        reply_sync_init = xcb_sync_initialize_reply(_ecore_xcb_conn,
+                                                    cookie_sync_init, NULL);
+       if (!reply_sync_init)
+         _ecore_xcb_event_sync_id = 0;
+        else
+          free(reply_sync_init);
+     }
+   if (_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY + 1;
+#endif /* ECORE_XCB_SYNC */
+
+#ifdef ECORE_XCB_FIXES
+   reply_xfixes = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
+   if (reply_xfixes)
+     _ecore_xcb_event_fixes_selection_id = reply_xfixes->first_event + XCB_XFIXES_SELECTION_NOTIFY;
+   if (_ecore_xcb_event_fixes_selection_id >= _ecore_xcb_event_handlers_num)
+     _ecore_xcb_event_handlers_num = _ecore_xcb_event_fixes_selection_id + 1;
+#endif /* ECORE_XCB_FIXES */
+
+#ifdef ECORE_XCB_XINERAMA
+   reply_xinerama = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xinerama_id);
+#endif /* ECORE_XCB_XINERAMA */
+
+#ifdef ECORE_XCB_XPRINT
+   reply_xprint = xcb_get_extension_data(_ecore_xcb_conn, &xcb_x_print_id);
+#endif /* ECORE_XCB_XPRINT */
+
+   /*********************/
+   /* Second round trip */
+   /*********************/
+
+   /* We ask for the QueryVersion request of the extensions */
+#ifdef ECORE_XCB_DAMAGE
+   _ecore_x_damage_init(reply_damage);
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_COMPOSITE
+   _ecore_x_composite_init(reply_composite);
+#endif /* ECORE_XCB_COMPOSITE */
+#ifdef ECORE_XCB_DPMS
+   _ecore_x_dpms_init(reply_dpms);
+#endif /* ECORE_XCB_DPMS */
+#ifdef ECORE_XCB_RANDR
+   _ecore_x_randr_init(reply_randr);
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+   _ecore_x_screensaver_init(reply_screensaver);
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+   _ecore_x_shape_init(reply_shape);
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+   _ecore_x_sync_init(reply_sync);
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+   _ecore_x_xfixes_init(reply_xfixes);
+#endif /* ECORE_XCB_FIXES */
+#ifdef ECORE_XCB_XINERAMA
+   _ecore_x_xinerama_init(reply_xinerama);
+#endif /* ECORE_XCB_XINERAMA */
+
+   /* we enable the Big Request extension if present */
+   max_request_length = xcb_get_maximum_request_length(_ecore_xcb_conn);
+
+   _ecore_xcb_event_handlers = calloc(_ecore_xcb_event_handlers_num, sizeof(void *));
+   if (!_ecore_xcb_event_handlers)
+     goto finalize_extensions;
+
+#ifdef ECORE_XCB_CURSOR
+   _ecore_xcb_xcursor = XcursorSupportsARGB(_ecore_xcb_conn);
+#endif /* ECORE_XCB_CURSOR */
+
+   _ecore_xcb_event_handlers[XCB_EVENT_ANY]         = _ecore_x_event_handle_any_event;
+   _ecore_xcb_event_handlers[XCB_KEY_PRESS]         = _ecore_x_event_handle_key_press;
+   _ecore_xcb_event_handlers[XCB_KEY_RELEASE]       = _ecore_x_event_handle_key_release;
+   _ecore_xcb_event_handlers[XCB_BUTTON_PRESS]      = _ecore_x_event_handle_button_press;
+   _ecore_xcb_event_handlers[XCB_BUTTON_RELEASE]    = _ecore_x_event_handle_button_release;
+   _ecore_xcb_event_handlers[XCB_MOTION_NOTIFY]     = _ecore_x_event_handle_motion_notify;
+   _ecore_xcb_event_handlers[XCB_ENTER_NOTIFY]      = _ecore_x_event_handle_enter_notify;
+   _ecore_xcb_event_handlers[XCB_LEAVE_NOTIFY]      = _ecore_x_event_handle_leave_notify;
+   _ecore_xcb_event_handlers[XCB_FOCUS_IN]          = _ecore_x_event_handle_focus_in;
+   _ecore_xcb_event_handlers[XCB_FOCUS_OUT]         = _ecore_x_event_handle_focus_out;
+   _ecore_xcb_event_handlers[XCB_KEYMAP_NOTIFY]     = _ecore_x_event_handle_keymap_notify;
+   _ecore_xcb_event_handlers[XCB_EXPOSE]            = _ecore_x_event_handle_expose;
+   _ecore_xcb_event_handlers[XCB_GRAPHICS_EXPOSURE] = _ecore_x_event_handle_graphics_expose;
+   _ecore_xcb_event_handlers[XCB_VISIBILITY_NOTIFY] = _ecore_x_event_handle_visibility_notify;
+   _ecore_xcb_event_handlers[XCB_CREATE_NOTIFY]     = _ecore_x_event_handle_create_notify;
+   _ecore_xcb_event_handlers[XCB_DESTROY_NOTIFY]    = _ecore_x_event_handle_destroy_notify;
+   _ecore_xcb_event_handlers[XCB_UNMAP_NOTIFY]      = _ecore_x_event_handle_unmap_notify;
+   _ecore_xcb_event_handlers[XCB_MAP_NOTIFY]        = _ecore_x_event_handle_map_notify;
+   _ecore_xcb_event_handlers[XCB_MAP_REQUEST]       = _ecore_x_event_handle_map_request;
+   _ecore_xcb_event_handlers[XCB_REPARENT_NOTIFY]   = _ecore_x_event_handle_reparent_notify;
+   _ecore_xcb_event_handlers[XCB_CONFIGURE_NOTIFY]  = _ecore_x_event_handle_configure_notify;
+   _ecore_xcb_event_handlers[XCB_CONFIGURE_REQUEST] = _ecore_x_event_handle_configure_request;
+   _ecore_xcb_event_handlers[XCB_GRAVITY_NOTIFY]    = _ecore_x_event_handle_gravity_notify;
+   _ecore_xcb_event_handlers[XCB_RESIZE_REQUEST]    = _ecore_x_event_handle_resize_request;
+   _ecore_xcb_event_handlers[XCB_CIRCULATE_NOTIFY]  = _ecore_x_event_handle_circulate_notify;
+   _ecore_xcb_event_handlers[XCB_CIRCULATE_REQUEST] = _ecore_x_event_handle_circulate_request;
+   _ecore_xcb_event_handlers[XCB_PROPERTY_NOTIFY]   = _ecore_x_event_handle_property_notify;
+   _ecore_xcb_event_handlers[XCB_SELECTION_CLEAR]   = _ecore_x_event_handle_selection_clear;
+   _ecore_xcb_event_handlers[XCB_SELECTION_REQUEST] = _ecore_x_event_handle_selection_request;
+   _ecore_xcb_event_handlers[XCB_SELECTION_NOTIFY]  = _ecore_x_event_handle_selection_notify;
+   _ecore_xcb_event_handlers[XCB_COLORMAP_NOTIFY]   = _ecore_x_event_handle_colormap_notify;
+   _ecore_xcb_event_handlers[XCB_CLIENT_MESSAGE]    = _ecore_x_event_handle_client_message;
+   _ecore_xcb_event_handlers[XCB_MAPPING_NOTIFY]    = _ecore_x_event_handle_mapping_notify;
+#ifdef ECORE_XCB_DAMAGE
+   if (_ecore_xcb_event_damage_id)
+     _ecore_xcb_event_handlers[_ecore_xcb_event_damage_id] = _ecore_x_event_handle_damage_notify;
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_RANDR
+   if (_ecore_xcb_event_randr_id)
+     _ecore_xcb_event_handlers[_ecore_xcb_event_randr_id] = _ecore_x_event_handle_randr_change;
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+   if (_ecore_xcb_event_screensaver_id)
+     _ecore_xcb_event_handlers[_ecore_xcb_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify;
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+   if (_ecore_xcb_event_shape_id)
+     _ecore_xcb_event_handlers[_ecore_xcb_event_shape_id] = _ecore_x_event_handle_shape_change;
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+   if (_ecore_xcb_event_sync_id)
+     {
+       _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_COUNTER_NOTIFY] =
+          _ecore_x_event_handle_sync_counter;
+       _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY] =
+          _ecore_x_event_handle_sync_alarm;
+     }
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+   if (_ecore_xcb_event_fixes_selection_id)
+     _ecore_xcb_event_handlers[_ecore_xcb_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify;
+#endif /* ECORE_XCB_FIXES */
+
+   if (!ECORE_X_EVENT_ANY)
+     {
+       ECORE_X_EVENT_ANY                      = ecore_event_type_new();
+       ECORE_X_EVENT_MOUSE_IN                 = ecore_event_type_new();
+       ECORE_X_EVENT_MOUSE_OUT                = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_FOCUS_IN          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_FOCUS_OUT         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_KEYMAP            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_DAMAGE            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CREATE            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_DESTROY           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_HIDE              = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHOW              = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHOW_REQUEST      = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_REPARENT          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CONFIGURE         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_GRAVITY           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_RESIZE_REQUEST    = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STACK             = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STACK_REQUEST     = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROPERTY          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_COLORMAP          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_MAPPING           = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_CLEAR          = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_REQUEST        = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_NOTIFY         = ecore_event_type_new();
+       ECORE_X_EVENT_CLIENT_MESSAGE           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHAPE             = ecore_event_type_new();
+       ECORE_X_EVENT_SCREENSAVER_NOTIFY       = ecore_event_type_new();
+       ECORE_X_EVENT_SYNC_COUNTER             = ecore_event_type_new();
+       ECORE_X_EVENT_SYNC_ALARM               = ecore_event_type_new();
+       ECORE_X_EVENT_SCREEN_CHANGE            = ecore_event_type_new();
+       ECORE_X_EVENT_DAMAGE_NOTIFY            = ecore_event_type_new();
+
+       ECORE_X_EVENT_WINDOW_DELETE_REQUEST                = ecore_event_type_new();
+       /*
+       ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE             = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE     = ecore_event_type_new();
+        ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE        = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE    = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE               = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE           = ecore_event_type_new();
+       */
+
+       ECORE_X_EVENT_DESKTOP_CHANGE             = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STATE_REQUEST       = ecore_event_type_new();
+       ECORE_X_EVENT_FRAME_EXTENTS_REQUEST      = ecore_event_type_new();
+       ECORE_X_EVENT_PING                       = ecore_event_type_new();
+
+       ECORE_X_EVENT_STARTUP_SEQUENCE_NEW       = ecore_event_type_new();
+       ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE    = ecore_event_type_new();
+       ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE    = ecore_event_type_new();
+     }
+
+   /* everything has these... unless its like a pda... :) */
+   ECORE_X_MODIFIER_SHIFT = _ecore_xcb_key_mask_get(XK_Shift_L);
+   ECORE_X_MODIFIER_CTRL  = _ecore_xcb_key_mask_get(XK_Control_L);
+
+   /* apple's xdarwin has no alt!!!! */
+   ECORE_X_MODIFIER_ALT   = _ecore_xcb_key_mask_get(XK_Alt_L);
+   if (!ECORE_X_MODIFIER_ALT)
+     ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Meta_L);
+   if (!ECORE_X_MODIFIER_ALT)
+     ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Super_L);
+
+   /* the windows key... a valid modifier :) */
+   ECORE_X_MODIFIER_WIN   = _ecore_xcb_key_mask_get(XK_Super_L);
+   if (!ECORE_X_MODIFIER_WIN)
+     ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Mode_switch);
+   if (!ECORE_X_MODIFIER_WIN)
+     ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Meta_L);
+
+   if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
+     ECORE_X_MODIFIER_WIN = 0;
+   if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
+     ECORE_X_MODIFIER_ALT = 0;
+
+   ECORE_X_LOCK_SCROLL    = _ecore_xcb_key_mask_get(XK_Scroll_Lock);
+   ECORE_X_LOCK_NUM       = _ecore_xcb_key_mask_get(XK_Num_Lock);
+   ECORE_X_LOCK_CAPS      = _ecore_xcb_key_mask_get(XK_Caps_Lock);
+
+   _ecore_xcb_fd_handler_handle =
+     ecore_main_fd_handler_add(xcb_get_file_descriptor(_ecore_xcb_conn),
+                              ECORE_FD_READ,
+                              _ecore_xcb_fd_handler, _ecore_xcb_conn,
+                              _ecore_xcb_fd_handler_buf, _ecore_xcb_conn);
+   if (!_ecore_xcb_fd_handler_handle)
+     goto free_event_handlers;
+
+   _ecore_xcb_filter_handler = ecore_event_filter_add(_ecore_xcb_event_filter_start, _ecore_xcb_event_filter_filter, _ecore_xcb_event_filter_end, NULL);
+
+   /* This is just to be anal about naming conventions */
+
+   _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW;
+   _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS;
+   _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING;
+   _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
+
+   _ecore_xcb_init_count++;
+
+   _ecore_xcb_private_window = ecore_x_window_override_new(0, -77, -777, 123, 456);
+
+   /* We finally get the replies of the QueryVersion request */
+#ifdef ECORE_XCB_DAMAGE
+   _ecore_x_damage_init_finalize();
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_COMPOSITE
+   _ecore_x_composite_init_finalize();
+#endif /* ECORE_XCB_COMPOSITE */
+#ifdef ECORE_XCB_DPMS
+   _ecore_x_dpms_init_finalize();
+#endif /* ECORE_XCB_DPMS */
+#ifdef ECORE_XCB_RANDR
+   _ecore_x_randr_init_finalize();
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+   _ecore_x_screensaver_init_finalize();
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+   _ecore_x_shape_init_finalize();
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+   _ecore_x_sync_init_finalize();
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+   _ecore_x_xfixes_init_finalize();
+#endif /* ECORE_XCB_FIXES */
+#ifdef ECORE_XCB_XINERAMA
+   _ecore_x_xinerama_init_finalize();
+#endif /* ECORE_XCB_XINERAMA */
+
+   return _ecore_xcb_init_count;
+
+ free_event_handlers:
+   free(_ecore_xcb_event_handlers);
+   _ecore_xcb_event_handlers = NULL;
+ finalize_extensions:
+   /* We get the replies of the QueryVersion request because we leave */
+#ifdef ECORE_XCB_DAMAGE
+   _ecore_x_damage_init_finalize();
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_COMPOSITE
+   _ecore_x_composite_init_finalize();
+#endif /* ECORE_XCB_COMPOSITE */
+#ifdef ECORE_XCB_DPMS
+   _ecore_x_dpms_init_finalize();
+#endif /* ECORE_XCB_DPMS */
+#ifdef ECORE_XCB_RANDR
+   _ecore_x_randr_init_finalize();
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+   _ecore_x_screensaver_init_finalize();
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+   _ecore_x_shape_init_finalize();
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+   _ecore_x_sync_init_finalize();
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+   _ecore_x_xfixes_init_finalize();
+#endif /* ECORE_XCB_FIXES */
+#ifdef ECORE_XCB_XINERAMA
+   _ecore_x_xinerama_init_finalize();
+#endif /* ECORE_XCB_XINERAMA */
+   ecore_event_shutdown();
+ close_connection:
+   _ecore_x_atom_init_finalize(atom_cookies);
+   xcb_disconnect(_ecore_xcb_conn);
+   _ecore_xcb_fd_handler_handle = NULL;
+   _ecore_xcb_conn = NULL;
+
+   return --_ecore_xcb_init_count;
+}
+
+static int
+_ecore_x_shutdown(int close_display)
+{
+   if (--_ecore_xcb_init_count != 0)
+     return _ecore_xcb_init_count;
+
+   if (!_ecore_xcb_conn) return _ecore_xcb_init_count;
+
+   if (close_display)
+      xcb_disconnect(_ecore_xcb_conn);
+   else
+      close(xcb_get_file_descriptor(_ecore_xcb_conn));
+   ecore_event_shutdown();
+   free(_ecore_xcb_event_handlers);
+   ecore_main_fd_handler_del(_ecore_xcb_fd_handler_handle);
+   ecore_event_filter_del(_ecore_xcb_filter_handler);
+   _ecore_xcb_fd_handler_handle = NULL;
+   _ecore_xcb_filter_handler = NULL;
+   _ecore_xcb_conn = NULL;
+   _ecore_xcb_event_handlers = NULL;
+   _ecore_x_selection_shutdown();
+   _ecore_x_dnd_shutdown();
+   ecore_x_netwm_shutdown();
+   _ecore_x_reply_shutdown();
+
+   return _ecore_xcb_init_count;
+}
+
+/**
+ * Shuts down the Ecore X library.
+ *
+ * In shutting down the library, the X display connection is terminated
+ * and any event handlers for it are removed.
+ *
+ * @return  The number of times the library has been initialized without
+ *          being shut down.
+ * @ingroup Ecore_Xcb_Init_Group
+ */
+EAPI int
+ecore_x_shutdown(void)
+{
+   return _ecore_x_shutdown(1);
+}
+
+/**
+ * Shuts down the Ecore X library.
+ *
+ * As ecore_xcb_shutdown, except do not close Display, only connection.
+ *
+ * @ingroup Ecore_Xcb_Init_Group
+ */
+EAPI int
+ecore_x_disconnect(void)
+{
+   return _ecore_x_shutdown(0);
+}
+
+/**
+ * @defgroup Ecore_Xcb_Display_Attr_Group X Display Attributes
+ *
+ * Functions that set and retrieve X display attributes.
+ */
+
+EAPI Ecore_X_Display *
+ecore_x_display_get(void)
+{
+   return NULL;
+}
+
+/**
+ * Retrieves the Ecore_X_Connection handle used for the current X connection.
+ * @return  The current X connection.
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI Ecore_X_Connection *
+ecore_x_connection_get(void)
+{
+   return (Ecore_X_Connection *)_ecore_xcb_conn;
+}
+
+/**
+ * Retrieves the X display file descriptor.
+ * @return  The current X display file descriptor.
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI int
+ecore_x_fd_get(void)
+{
+   return xcb_get_file_descriptor(_ecore_xcb_conn);
+}
+
+/**
+ * Retrieves the Ecore_X_Screen handle used for the current X connection.
+ * @return  The current default screen.
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI Ecore_X_Screen *
+ecore_x_default_screen_get(void)
+{
+   return (Ecore_X_Screen *)_ecore_xcb_screen;
+}
+
+/**
+ * Sets the timeout for a double and triple clicks to be flagged.
+ *
+ * This sets the time between clicks before the double_click flag is
+ * set in a button down event. If 3 clicks occur within double this
+ * time, the triple_click flag is also set.
+ *
+ * @param   t The time in seconds
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI void
+ecore_x_double_click_time_set(double t)
+{
+   if (t < 0.0) t = 0.0;
+   _ecore_xcb_double_click_time = t;
+}
+
+/**
+ * Retrieves the double and triple click flag timeout.
+ *
+ * See @ref ecore_xcb_double_click_time_set for more information.
+ *
+ * @return  The timeout for double clicks in seconds.
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI double
+ecore_x_double_click_time_get(void)
+{
+   return _ecore_xcb_double_click_time;
+}
+
+/**
+ * @defgroup Ecore_Xcb_Flush_Group X Synchronization Functions
+ *
+ * Functions that ensure that all commands that have been issued by the
+ * Ecore X library have been sent to the server.
+ */
+
+/**
+ * Sends all X commands in the X Display buffer.
+ * @ingroup Ecore_Xcb_Flush_Group
+ */
+EAPI void
+ecore_x_flush(void)
+{
+   xcb_flush(_ecore_xcb_conn);
+}
+
+/**
+ * Flushes the command buffer and waits until all requests have been
+ * processed by the server.
+ * @ingroup Ecore_Xcb_Flush_Group
+ */
+EAPI void
+ecore_x_sync(void)
+{
+   free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
+}
+
+/**
+ * Kill all clients with subwindows under a given window.
+ *
+ * You can kill all clients connected to the X server by using
+ * @ref ecore_x_window_root_list to get a list of root windows, and
+ * then passing each root window to this function.
+ *
+ * @param root The window whose children will be killed.
+ */
+EAPI void
+ecore_x_killall(Ecore_X_Window root)
+{
+   int screens;
+   int i;
+
+   xcb_grab_server(_ecore_xcb_conn);
+   screens = xcb_setup_roots_iterator (xcb_get_setup (_ecore_xcb_conn)).rem;
+
+   /* Tranverse window tree starting from root, and drag each
+    * before the firing squad */
+   for (i = 0; i < screens; ++i)
+     {
+        xcb_query_tree_cookie_t cookie;
+        xcb_query_tree_reply_t *reply;
+
+        cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root);
+        reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
+        if (reply)
+          {
+            xcb_window_iterator_t iter;
+
+            iter = xcb_query_tree_children_iterator(reply);
+            for (; iter.rem; xcb_window_next(&iter))
+               xcb_kill_client(_ecore_xcb_conn, *iter.data);
+            free(reply);
+          }
+     }
+
+   xcb_ungrab_server(_ecore_xcb_conn);
+   free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
+}
+
+/**
+ * Kill a specific client
+ *
+ * You can kill a specific client woning window @p window
+ *
+ * @param window Window of the client to be killed
+ */
+EAPI void
+ecore_x_kill(Ecore_X_Window window)
+{
+   xcb_kill_client(_ecore_xcb_conn, window);
+}
+
+/**
+ * Return the last event time
+ */
+EAPI Ecore_X_Time
+ecore_x_current_time_get(void)
+{
+   return _ecore_xcb_event_last_time;
+}
+
+static void
+handle_event(xcb_generic_event_t *ev)
+{
+   uint8_t response_type = ev->response_type & ~0x80;
+
+   if (response_type < _ecore_xcb_event_handlers_num)
+     {
+       if (_ecore_xcb_event_handlers[XCB_EVENT_ANY])
+         _ecore_xcb_event_handlers[XCB_EVENT_ANY] (ev);
+
+       if (_ecore_xcb_event_handlers[response_type])
+         _ecore_xcb_event_handlers[response_type] (ev);
+     }
+}
+
+static int
+_ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   xcb_connection_t    *c;
+   xcb_generic_event_t *ev;
+
+   c = (xcb_connection_t *)data;
+
+/*    INF ("nbr events: %d", _ecore_xcb_event_handlers_num); */
+
+   /* We check if _ecore_xcb_event_buffered is NULL or not */
+   if (_ecore_xcb_event_buffered)
+     handle_event(_ecore_xcb_event_buffered);
+
+   while ((ev = xcb_poll_for_event(c)))
+     handle_event(ev);
+
+   return 1;
+}
+
+static int
+_ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   xcb_connection_t *c;
+
+   c = (xcb_connection_t *)data;
+
+   _ecore_xcb_event_buffered = xcb_poll_for_event(c);
+   if (!_ecore_xcb_event_buffered)
+     return 0;
+
+   return 1;
+}
+
+/* FIXME: possible roundtrip */
+/* FIXME: fix xcb_keysyms. It's ugly !! (reply in xcb_key_symbols_get_keysym) */
+static int
+_ecore_xcb_key_mask_get(xcb_keysym_t sym)
+{
+   xcb_keycode_iterator_t            iter;
+   xcb_get_modifier_mapping_cookie_t cookie;
+   xcb_get_modifier_mapping_reply_t *reply;
+   xcb_key_symbols_t                *symbols;
+   xcb_keysym_t                      sym2;
+   int                               i, j;
+   const int                         masks[8] =
+     {
+        XCB_MOD_MASK_SHIFT,
+        XCB_MOD_MASK_LOCK,
+        XCB_MOD_MASK_CONTROL,
+        XCB_MOD_MASK_1,
+        XCB_MOD_MASK_2,
+        XCB_MOD_MASK_3,
+        XCB_MOD_MASK_4,
+        XCB_MOD_MASK_5
+     };
+
+   cookie = xcb_get_modifier_mapping_unchecked(_ecore_xcb_conn);
+   symbols = xcb_key_symbols_alloc(_ecore_xcb_conn);
+
+   reply = xcb_get_modifier_mapping_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply)
+     {
+        xcb_key_symbols_free(symbols);
+
+        return 0;
+     }
+
+   iter = xcb_get_modifier_mapping_keycodes_iterator(reply);
+
+   for (i = 0; iter.rem; xcb_keycode_next(&iter), i++)
+     {
+       for (j = 0; j < 8; j++)
+         {
+            sym2 = xcb_key_symbols_get_keysym(symbols, *iter.data, j);
+            if (sym2 != 0) break;
+         }
+       if (sym2 == sym)
+         {
+            int mask;
+
+            mask = masks[j];
+            free(reply);
+            xcb_key_symbols_free(symbols);
+            return mask;
+         }
+     }
+
+   free(reply);
+   xcb_key_symbols_free(symbols);
+
+  return 0;
+}
+
+typedef struct _Ecore_X_Filter_Data Ecore_X_Filter_Data;
+
+struct _Ecore_X_Filter_Data
+{
+   int last_event_type;
+};
+
+static void *
+_ecore_xcb_event_filter_start(void *data __UNUSED__)
+{
+   Ecore_X_Filter_Data *filter_data;
+
+   filter_data = calloc(1, sizeof(Ecore_X_Filter_Data));
+   return filter_data;
+}
+
+static int
+_ecore_xcb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__)
+{
+   Ecore_X_Filter_Data *filter_data;
+
+   filter_data = loop_data;
+   if (!filter_data) return 1;
+   if (type == ECORE_EVENT_MOUSE_MOVE)
+     {
+       if ((filter_data->last_event_type) == ECORE_EVENT_MOUSE_MOVE)
+         {
+            filter_data->last_event_type = type;
+            return 0;
+         }
+     }
+   filter_data->last_event_type = type;
+   return 1;
+}
+
+static void
+_ecore_xcb_event_filter_end(void *data __UNUSED__, void *loop_data)
+{
+   Ecore_X_Filter_Data *filter_data;
+
+   filter_data = loop_data;
+   if (filter_data) free(filter_data);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/* FIXME: these funcs need categorising */
+/*****************************************************************************/
+
+
+
+
+/**
+ * Get a list of all the root windows on the server.
+ *
+ * @note   The returned array will need to be freed after use.
+ * @param  num_ret Pointer to integer to put number of windows returned in.
+ * @return An array of all the root windows.  @c NULL is returned if memory
+ *         could not be allocated for the list, or if @p num_ret is @c NULL.
+ */
+EAPI Ecore_X_Window *
+ecore_x_window_root_list(int *num_ret)
+{
+   xcb_screen_iterator_t iter;
+   const xcb_setup_t    *setup;
+   uint8_t               i;
+   uint8_t               num;
+   Ecore_X_Window     *roots;
+/* #ifdef ECORE_XCBXPRINT */
+/*    int xp_base, xp_err_base; */
+/* #endif /\* ECORE_XCBXPRINT *\/ */
+
+   if (!num_ret) return NULL;
+   *num_ret = 0;
+
+   /* FIXME: todo... */
+/* #ifdef ECORE_XCBXPRINT */
+/*    num = ScreenCount(_ecore_xcb_conn); */
+/*    if (ecore_xcb_xprint_query()) */
+/*      { */
+/*     Screen **ps = NULL; */
+/*     int psnum = 0; */
+
+/*     ps = XpQueryScreens(_ecore_xcb_conn, &psnum); */
+/*     if (ps) */
+/*       { */
+/*          int overlap, j; */
+
+/*          overlap = 0; */
+/*          for (i = 0; i < num; i++) */
+/*            { */
+/*               for (j = 0; j < psnum; j++) */
+/*                 { */
+/*                    if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */
+/*                      overlap++; */
+/*                 } */
+/*            } */
+/*          roots = malloc((num - overlap) * sizeof(Ecore_X_Window)); */
+/*          if (roots) */
+/*            { */
+/*               int k; */
+
+/*               k = 0; */
+/*               for (i = 0; i < num; i++) */
+/*                 { */
+/*                    int is_print; */
+
+/*                    is_print = 0; */
+/*                    for (j = 0; j < psnum; j++) */
+/*                      { */
+/*                         if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */
+/*                           { */
+/*                              is_print = 1; */
+/*                              break; */
+/*                           } */
+/*                      } */
+/*                    if (!is_print) */
+/*                      { */
+/*                         roots[k] = RootWindow(_ecore_xcb_conn, i); */
+/*                         k++; */
+/*                      } */
+/*                 } */
+/*               *num_ret = k; */
+/*            } */
+/*          XFree(ps); */
+/*       } */
+/*     else */
+/*       { */
+/*          roots = malloc(num * sizeof(Ecore_X_Window)); */
+/*          if (!roots) return NULL; */
+/*          *num_ret = num; */
+/*          for (i = 0; i < num; i++) */
+/*            roots[i] = RootWindow(_ecore_xcb_conn, i); */
+/*       } */
+/*      } */
+/*    else */
+/*      { */
+/*     roots = malloc(num * sizeof(Ecore_X_Window)); */
+/*     if (!roots) return NULL; */
+/*     *num_ret = num; */
+/*     for (i = 0; i < num; i++) */
+/*       roots[i] = RootWindow(_ecore_xcb_conn, i); */
+/*      } */
+/* #else */
+   setup = xcb_get_setup (_ecore_xcb_conn);
+   iter = xcb_setup_roots_iterator (setup);
+   num = setup->roots_len;
+   roots = malloc(num * sizeof(Ecore_X_Window));
+   if (!roots) return NULL;
+
+   *num_ret = num;
+   for (i = 0; iter.rem; xcb_screen_next(&iter), i++)
+     roots[i] = iter.data->root;
+/* #endif /\* ECORE_XCBXPRINT *\/ */
+
+   return roots;
+}
+
+EAPI Ecore_X_Window
+ecore_x_window_root_first_get(void)
+{
+   Ecore_X_Window *roots = NULL;
+   Ecore_X_Window  root;
+   int             num;
+
+   roots = ecore_x_window_root_list(&num);
+   if(!(roots)) return 0;
+
+   if (num > 0)
+      root = roots[0];
+   else
+      root = 0;
+
+   free(roots);
+   return root;
+}
+
+/* FIXME: todo */
+
+static void _ecore_x_window_manage_error(void *data);
+
+static int _ecore_xcb_window_manage_failed = 0;
+static void
+_ecore_x_window_manage_error(void *data __UNUSED__)
+{
+/*    if ((ecore_xcb_error_request_get() == X_ChangeWindowAttributes) && */
+/*        (ecore_xcb_error_code_get() == BadAccess)) */
+/*      _ecore_xcb_window_manage_failed = 1; */
+}
+
+/* FIXME: round trip */
+EAPI int
+ecore_x_window_manage(Ecore_X_Window window)
+{
+   xcb_get_window_attributes_cookie_t cookie_attr;
+   xcb_get_input_focus_cookie_t       cookie_sync;
+   xcb_get_window_attributes_reply_t *reply_attr;
+   xcb_get_input_focus_reply_t       *reply_sync;
+   uint32_t                           value_list;
+
+   cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
+   cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
+
+   reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
+   if (!reply_attr)
+     {
+        reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL);
+        if (reply_sync) free(reply_sync);
+        return 0;
+     }
+
+   reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL);
+   if (reply_sync) free(reply_sync);
+
+   _ecore_xcb_window_manage_failed = 0;
+   /* FIXME: no error code yet */
+   /* ecore_xcb_error_handler_set(_ecore_xcb_window_manage_error, NULL); */
+
+   value_list =
+     XCB_EVENT_MASK_KEY_PRESS             |
+     XCB_EVENT_MASK_KEY_RELEASE           |
+     XCB_EVENT_MASK_ENTER_WINDOW          |
+     XCB_EVENT_MASK_LEAVE_WINDOW          |
+     XCB_EVENT_MASK_STRUCTURE_NOTIFY      |
+     XCB_EVENT_MASK_RESIZE_REDIRECT       |
+     XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY   |
+     XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
+     XCB_EVENT_MASK_PROPERTY_CHANGE       |
+     reply_attr->your_event_mask;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_EVENT_MASK,
+                                &value_list);
+   free(reply_attr);
+
+   cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
+   if (reply_sync) free(reply_sync);
+
+   /* FIXME: no error code yet */
+   /* ecore_xcb_error_handler_set(NULL, NULL); */
+   if (_ecore_xcb_window_manage_failed)
+     {
+       _ecore_xcb_window_manage_failed = 0;
+       return 0;
+     }
+
+   return 1;
+}
+
+
+
+
+
+
+
+
+EAPI int
+ecore_x_pointer_control_set(int accel_num,
+                            int accel_denom,
+                            int threshold)
+{
+   xcb_change_pointer_control(_ecore_xcb_conn, 
+                              accel_num, accel_denom, threshold,
+                              1, 1);
+   return 1;
+}
+
+EAPI void
+ecore_x_pointer_control_get_prefetch(void)
+{
+   xcb_get_pointer_control_cookie_t cookie;
+
+   cookie = xcb_get_pointer_control_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+EAPI void
+ecore_x_pointer_control_get_fetch(void)
+{
+   xcb_get_pointer_control_cookie_t cookie;
+   xcb_get_pointer_control_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_pointer_control_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+EAPI int
+ecore_x_pointer_control_get(int *accel_num,
+                            int *accel_denom,
+                            int *threshold)
+{
+   xcb_get_pointer_control_reply_t *reply;
+
+   if (accel_num) *accel_num = 0;
+   if (accel_denom) *accel_denom = 1;
+   if (threshold) *threshold = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   if (accel_num) *accel_num = reply->acceleration_numerator;
+   if (accel_denom) *accel_denom = reply->acceleration_denominator;
+   if (threshold) *threshold = reply->threshold;
+
+   return 1;
+}
+
+EAPI int
+ecore_x_pointer_mapping_set(unsigned char *map,
+                           int nmap)
+{
+   xcb_set_pointer_mapping(_ecore_xcb_conn, nmap, map);
+   return 1;
+}
+
+EAPI void
+ecore_x_pointer_mapping_get_prefetch(void)
+{
+   xcb_get_pointer_mapping_cookie_t cookie;
+
+   cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+EAPI void
+ecore_x_pointer_mapping_get_fetch(void)
+{
+   xcb_get_pointer_mapping_cookie_t cookie;
+   xcb_get_pointer_mapping_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+EAPI int
+ecore_x_pointer_mapping_get(unsigned char *map,
+                            int nmap)
+{
+   xcb_get_pointer_mapping_cookie_t cookie;
+   xcb_get_pointer_mapping_reply_t *reply;
+   uint8_t                         *tmp;
+   int                              i;
+
+   cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn);
+   reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply) return 0;
+
+   if (nmap > xcb_get_pointer_mapping_map_length(reply))
+     return 0;
+
+   tmp = xcb_get_pointer_mapping_map(reply);
+
+   for (i = 0; i < nmap; i++)
+     map[i] = tmp[i];
+
+   return 1;
+}
+
+EAPI int
+ecore_x_pointer_grab(Ecore_X_Window window)
+{
+   xcb_grab_pointer_cookie_t cookie;
+   xcb_grab_pointer_reply_t *reply;
+
+   cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window,
+                                       XCB_EVENT_MASK_BUTTON_PRESS   |
+                                       XCB_EVENT_MASK_BUTTON_RELEASE |
+                                       XCB_EVENT_MASK_ENTER_WINDOW   |
+                                       XCB_EVENT_MASK_LEAVE_WINDOW   |
+                                       XCB_EVENT_MASK_POINTER_MOTION,
+                                       XCB_GRAB_MODE_ASYNC,
+                                       XCB_GRAB_MODE_ASYNC,
+                                       XCB_NONE, XCB_NONE,
+                                       XCB_CURRENT_TIME);
+   reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply)
+      return 0;
+
+   free(reply);
+
+   return 1;
+}
+
+EAPI int
+ecore_x_pointer_confine_grab(Ecore_X_Window window)
+{
+   xcb_grab_pointer_cookie_t cookie;
+   xcb_grab_pointer_reply_t *reply;
+
+   cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window,
+                                       XCB_EVENT_MASK_BUTTON_PRESS   |
+                                       XCB_EVENT_MASK_BUTTON_RELEASE |
+                                       XCB_EVENT_MASK_ENTER_WINDOW   |
+                                       XCB_EVENT_MASK_LEAVE_WINDOW   |
+                                       XCB_EVENT_MASK_POINTER_MOTION,
+                                       XCB_GRAB_MODE_ASYNC,
+                                       XCB_GRAB_MODE_ASYNC,
+                                       window, XCB_NONE,
+                                       XCB_CURRENT_TIME);
+   reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply)
+      return 0;
+
+   free(reply);
+
+   return 1;
+}
+
+EAPI void
+ecore_x_pointer_ungrab(void)
+{
+   xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME);
+}
+
+EAPI int
+ecore_x_pointer_warp(Ecore_X_Window window,
+                     int            x,
+                     int            y)
+{
+  xcb_warp_pointer(_ecore_xcb_conn, XCB_NONE, window, 0, 0, 0, 0, x, y);
+
+  return 1;
+}
+
+EAPI int
+ecore_x_keyboard_grab(Ecore_X_Window window)
+{
+   xcb_grab_keyboard_cookie_t cookie;
+   xcb_grab_keyboard_reply_t *reply;
+
+   cookie = xcb_grab_keyboard_unchecked(_ecore_xcb_conn, 0, window,
+                                        XCB_CURRENT_TIME,
+                                        XCB_GRAB_MODE_ASYNC,
+                                        XCB_GRAB_MODE_ASYNC);
+   reply = xcb_grab_keyboard_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply)
+      return 0;
+
+   free(reply);
+
+   return 1;
+}
+
+EAPI void
+ecore_x_keyboard_ungrab(void)
+{
+   xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME);
+}
+
+EAPI void
+ecore_x_grab(void)
+{
+   _ecore_xcb_grab_count++;
+
+   if (_ecore_xcb_grab_count == 1)
+      xcb_grab_server(_ecore_xcb_conn);
+}
+
+EAPI void
+ecore_x_ungrab(void)
+{
+   _ecore_xcb_grab_count--;
+   if (_ecore_xcb_grab_count < 0)
+      _ecore_xcb_grab_count = 0;
+
+   if (_ecore_xcb_grab_count == 0)
+   {
+      xcb_ungrab_server(_ecore_xcb_conn);
+      free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
+   }
+}
+
+int      _ecore_window_grabs_num = 0;
+Ecore_X_Window  *_ecore_window_grabs = NULL;
+int    (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event);
+void    *_ecore_window_grab_replay_data;
+
+EAPI void
+ecore_x_passive_grab_replay_func_set(int (*func) (void *data,
+                                                  int   event_type,
+                                                  void *event),
+                                     void *data)
+{
+   _ecore_window_grab_replay_func = func;
+   _ecore_window_grab_replay_data = data;
+}
+
+EAPI void
+ecore_x_window_button_grab(Ecore_X_Window     window,
+                           int                button,
+                           Ecore_X_Event_Mask event_mask,
+                           int                mod,
+                           int                any_mod)
+{
+   int      i;
+   uint16_t m;
+   uint16_t locks[8];
+   uint16_t ev;
+
+   m = _ecore_xcb_event_modifier(mod);
+   if (any_mod) m = XCB_BUTTON_MASK_ANY;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   ev = event_mask;
+   for (i = 0; i < 8; i++)
+     xcb_grab_button(_ecore_xcb_conn, 0, window, ev,
+                     XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
+                     XCB_NONE, XCB_NONE, button, m | locks[i]);
+   _ecore_window_grabs_num++;
+   _ecore_window_grabs = realloc(_ecore_window_grabs,
+                                _ecore_window_grabs_num * sizeof(Ecore_X_Window));
+   _ecore_window_grabs[_ecore_window_grabs_num - 1] = window;
+}
+
+void
+_ecore_x_sync_magic_send(int            val,
+                         Ecore_X_Window swindow)
+{
+   xcb_client_message_event_t ev;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.window = _ecore_xcb_private_window;
+   ev.type = 27777;
+   ev.data.data32[0] = 0x7162534;
+   ev.data.data32[1] = 0x10000000 + val;
+   ev.data.data32[2] = swindow;
+
+   xcb_send_event(_ecore_xcb_conn, 0, _ecore_xcb_private_window,
+                  XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
+}
+
+void
+_ecore_x_window_grab_remove(Ecore_X_Window window)
+{
+   int i, shuffle = 0;
+
+   if (_ecore_window_grabs_num > 0)
+     {
+       for (i = 0; i < _ecore_window_grabs_num; i++)
+         {
+            if (shuffle) _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
+            if ((!shuffle) && (_ecore_window_grabs[i] == window))
+              shuffle = 1;
+         }
+       if (shuffle)
+         {
+            _ecore_window_grabs_num--;
+            _ecore_window_grabs = realloc(_ecore_window_grabs,
+                                          _ecore_window_grabs_num * sizeof(Ecore_X_Window));
+         }
+     }
+}
+
+EAPI void
+ecore_x_window_button_ungrab(Ecore_X_Window window,
+                             int            button,
+                             int            mod,
+                             int            any_mod)
+{
+   int      i;
+   uint16_t m;
+   uint16_t locks[8];
+
+   m = _ecore_xcb_event_modifier(mod);
+   if (any_mod) m = XCB_BUTTON_MASK_ANY;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     xcb_ungrab_button(_ecore_xcb_conn, button, window, m | locks[i]);
+   _ecore_x_sync_magic_send(1, window);
+}
+
+int                _ecore_key_grabs_num = 0;
+Ecore_X_Window  *_ecore_key_grabs = NULL;
+
+EAPI void
+ecore_x_window_key_grab(Ecore_X_Window window,
+                        const char    *key,
+                        int            mod,
+                        int            any_mod)
+{
+   xcb_keycode_t keycode = 0;
+   uint16_t      m;
+   uint16_t      locks[8];
+   int           i;
+
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   /* FIXME: TODO... */
+
+/*    else */
+/*      { */
+/*         KeySym              keysym; */
+
+/*     keysym = XStringToKeysym(key); */
+/*     if (keysym == NoSymbol) return; */
+/*     keycode  = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */
+/*      } */
+   if (keycode == 0) return;
+
+   m = _ecore_xcb_event_modifier(mod);
+   if (any_mod) m = XCB_BUTTON_MASK_ANY;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     xcb_grab_key(_ecore_xcb_conn, 1, window, m | locks[i], keycode,
+                  XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
+   _ecore_key_grabs_num++;
+   _ecore_key_grabs = realloc(_ecore_key_grabs,
+                             _ecore_key_grabs_num * sizeof(Ecore_X_Window));
+   _ecore_key_grabs[_ecore_key_grabs_num - 1] = window;
+}
+
+void
+_ecore_x_key_grab_remove(Ecore_X_Window window)
+{
+   int i, shuffle = 0;
+
+   if (_ecore_key_grabs_num > 0)
+     {
+       for (i = 0; i < _ecore_key_grabs_num; i++)
+         {
+            if (shuffle) _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
+            if ((!shuffle) && (_ecore_key_grabs[i] == window))
+              shuffle = 1;
+         }
+       if (shuffle)
+         {
+            _ecore_key_grabs_num--;
+            _ecore_key_grabs = realloc(_ecore_key_grabs,
+                                       _ecore_key_grabs_num * sizeof(Ecore_X_Window));
+         }
+     }
+}
+
+EAPI void
+ecore_x_window_key_ungrab(Ecore_X_Window window,
+                          const char    *key,
+                          int            mod,
+                          int            any_mod)
+{
+   xcb_keycode_t keycode = 0;
+   uint16_t      m;
+   uint16_t      locks[8];
+   int           i;
+
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   /* FIXME: todo... */
+
+/*    else */
+/*      { */
+/*         KeySym              keysym; */
+
+/*     keysym = XStringToKeysym(key); */
+/*     if (keysym == NoSymbol) return; */
+/*     keycode  = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */
+/*      } */
+   if (keycode == 0) return;
+
+   m = _ecore_xcb_event_modifier(mod);
+   if (any_mod) m = XCB_BUTTON_MASK_ANY;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     xcb_ungrab_key(_ecore_xcb_conn, keycode, window, m | locks[i]);
+   _ecore_x_sync_magic_send(2, window);
+}
+
+/**
+ * Send client message with given type and format 32.
+ *
+ * @param window  The window the message is sent to.
+ * @param type    The client message type.
+ * @param mask    The client message mask.
+ * @param d0      The client message data item 1
+ * @param d1      The client message data item 2
+ * @param d2      The client message data item 3
+ * @param d3      The client message data item 4
+ * @param d4      The client message data item 5
+ *
+ * @return !0 on success.
+ */
+EAPI int
+ecore_x_client_message32_send(Ecore_X_Window     window,
+                              Ecore_X_Atom       type,
+                              Ecore_X_Event_Mask mask,
+                              long               d0,
+                              long               d1,
+                              long               d2,
+                              long               d3,
+                              long               d4)
+{
+    xcb_client_message_event_t ev;
+
+    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+    ev.format = 32;
+    ev.window = window;
+    ev.type = type;
+    ev.data.data32[0] = d0;
+    ev.data.data32[1] = d1;
+    ev.data.data32[2] = d2;
+    ev.data.data32[3] = d3;
+    ev.data.data32[4] = d4;
+
+    xcb_send_event(_ecore_xcb_conn, 0, window, mask, (const char *)&ev);
+
+    return 1;
+}
+
+/**
+ * Send client message with given type and format 8.
+ *
+ * @param window  The window the message is sent to.
+ * @param type    The client message type.
+ * @param data    Data to be sent.
+ * @param len     Number of data bytes, max 20.
+ *
+ * @return !0 on success.
+ */
+EAPI int
+ecore_x_client_message8_send(Ecore_X_Window window,
+                             Ecore_X_Atom   type,
+                             const void    *data,
+                             int            len)
+{
+   xcb_client_message_event_t ev;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 8;
+   ev.window = window;
+   ev.type = type;
+   if (len > 20)
+      len = 20;
+   memcpy(ev.data.data8, data, len);
+   memset(ev.data.data8 + len, 0, 20 - len);
+
+   xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
+
+   return 1;
+}
+
+/* FIXME: round trip */
+EAPI int
+ecore_x_mouse_move_send(Ecore_X_Window window,
+                        int            x,
+                        int            y)
+{
+   xcb_motion_notify_event_t          ev;
+   xcb_get_geometry_cookie_t          cookie_geom;
+   xcb_translate_coordinates_cookie_t cookie_trans;
+   xcb_get_geometry_reply_t          *reply_geom;
+   xcb_translate_coordinates_reply_t *reply_trans;
+
+   cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
+   reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+   if (!reply_geom) return 0;
+
+   cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
+   reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
+   if (!reply_trans)
+     {
+        free(reply_geom);
+        return 0;
+     }
+
+   ev.response_type = XCB_MOTION_NOTIFY;
+   ev.detail = 0;
+   ev.time = _ecore_xcb_event_last_time;
+   ev.root = reply_geom->root;
+   ev.event = window;
+   ev.child = window;
+   ev.root_x = reply_trans->dst_x;
+   ev.root_y = reply_trans->dst_y;
+   ev.event_x = x;
+   ev.event_y = y;
+   ev.state = 0;
+   ev.same_screen = 1;
+
+   xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev);
+
+   free(reply_geom);
+   free(reply_trans);
+
+   return 1;
+}
+
+/* FIXME: round trip */
+EAPI int
+ecore_x_mouse_down_send(Ecore_X_Window window,
+                        int            x,
+                        int            y,
+                        int              button)
+{
+   xcb_button_press_event_t           ev;
+   xcb_get_geometry_cookie_t          cookie_geom;
+   xcb_translate_coordinates_cookie_t cookie_trans;
+   xcb_get_geometry_reply_t          *reply_geom;
+   xcb_translate_coordinates_reply_t *reply_trans;
+
+   cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
+   reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+   if (!reply_geom) return 0;
+
+   cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
+   reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
+   if (!reply_trans)
+     {
+        free(reply_geom);
+        return 0;
+     }
+
+   ev.response_type = XCB_BUTTON_PRESS;
+   ev.detail = button;
+   ev.time = _ecore_xcb_event_last_time;
+   ev.root = reply_geom->root;
+   ev.event = window;
+   ev.child = window;
+   ev.root_x = reply_trans->dst_x;
+   ev.root_y = reply_trans->dst_y;
+   ev.event_x = x;
+   ev.event_y = y;
+   ev.state = 1 << button;
+   ev.same_screen = 1;
+
+   xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev);
+
+   free(reply_geom);
+   free(reply_trans);
+
+   return 1;
+}
+
+/* FIXME: round trip */
+EAPI int
+ecore_x_mouse_up_send(Ecore_X_Window window,
+                      int            x,
+                      int            y,
+                      int            button)
+{
+   xcb_button_release_event_t         ev;
+   xcb_get_geometry_cookie_t          cookie_geom;
+   xcb_translate_coordinates_cookie_t cookie_trans;
+   xcb_get_geometry_reply_t          *reply_geom;
+   xcb_translate_coordinates_reply_t *reply_trans;
+
+   cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
+   reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+   if (!reply_geom) return 0;
+
+   cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
+   reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
+   if (!reply_trans)
+     {
+        free(reply_geom);
+        return 0;
+     }
+
+   ev.response_type = XCB_BUTTON_RELEASE;
+   ev.detail = button;
+   ev.time = _ecore_xcb_event_last_time;
+   ev.root = reply_geom->root;
+   ev.event = window;
+   ev.child = window;
+   ev.root_x = reply_trans->dst_x;
+   ev.root_y = reply_trans->dst_y;
+   ev.event_x = x;
+   ev.event_y = y;
+   ev.state = 0;
+   ev.same_screen = 1;
+
+   xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev);
+
+   free(reply_geom);
+   free(reply_trans);
+
+   return 1;
+}
+
+EAPI void
+ecore_x_focus_reset(void)
+{
+   xcb_set_input_focus(_ecore_xcb_conn,
+                       (uint8_t)XCB_INPUT_FOCUS_POINTER_ROOT,
+                       XCB_INPUT_FOCUS_POINTER_ROOT,
+                       XCB_CURRENT_TIME);
+}
+
+EAPI void
+ecore_x_events_allow_all(void)
+{
+   xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME);
+}
+
+EAPI void
+ecore_x_pointer_last_xy_get(int *x,
+                            int *y)
+{
+   if (x) *x = _ecore_xcb_event_last_root_x;
+   if (y) *y = _ecore_xcb_event_last_root_y;
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+static int
+_ecore_xcb_event_modifier(unsigned int state)
+{
+   int xmodifiers = 0;
+
+   if (state & ECORE_EVENT_MODIFIER_SHIFT) xmodifiers |= ECORE_X_MODIFIER_SHIFT;
+   if (state & ECORE_EVENT_MODIFIER_CTRL) xmodifiers |= ECORE_X_MODIFIER_CTRL;
+   if (state & ECORE_EVENT_MODIFIER_ALT) xmodifiers |= ECORE_X_MODIFIER_ALT;
+   if (state & ECORE_EVENT_MODIFIER_WIN) xmodifiers |= ECORE_X_MODIFIER_WIN;
+   if (state & ECORE_EVENT_LOCK_SCROLL) xmodifiers |= ECORE_X_LOCK_SCROLL;
+   if (state & ECORE_EVENT_LOCK_NUM) xmodifiers |= ECORE_X_LOCK_NUM;
+   if (state & ECORE_EVENT_LOCK_CAPS) xmodifiers |= ECORE_X_LOCK_CAPS;
+
+   return xmodifiers;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_atom.c b/src/lib/ecore_x/xcb/ecore_xcb_atom.c
new file mode 100644 (file)
index 0000000..fa5bf24
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <string.h>
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Atom_Group XCB Atom Functions
+ *
+ * Functions that operate on atoms.
+ */
+
+/*********/
+/* Atoms */
+/*********/
+
+#include "ecore_x_atoms_decl.h"
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_atom_init and
+   _ecore_xcb_atom_init_finalize. The first one gets the cookies and
+   the second one gets the replies and set the atoms. */
+
+#define FETCH_ATOM(s) \
+   atom_cookies[i] = xcb_intern_atom(_ecore_xcb_conn, 0, strlen(s), s); \
+   i++
+
+#define FETCH_ATOM_FINALIZE(x) \
+   reply = xcb_intern_atom_reply(_ecore_xcb_conn, atom_cookies[i], NULL); \
+   x = reply->atom; \
+   free(reply); \
+   i++;
+
+void
+_ecore_x_atom_init(xcb_intern_atom_cookie_t *atom_cookies)
+{
+   int i = 0;
+
+   /* generic atoms */
+   FETCH_ATOM("COMPOUND_TEXT");
+   FETCH_ATOM("FILE_NAME");
+   FETCH_ATOM("TEXT");
+   FETCH_ATOM("UTF8_STRING");
+
+   /* dnd atoms */
+   FETCH_ATOM("JXSelectionWindowProperty");
+   FETCH_ATOM("XdndSelection");
+   FETCH_ATOM("XdndAware");
+   FETCH_ATOM("XdndEnter");
+   FETCH_ATOM("XdndTypeList");
+   FETCH_ATOM("XdndPosition");
+   FETCH_ATOM("XdndActionCopy");
+   FETCH_ATOM("XdndActionMove");
+   FETCH_ATOM("XdndActionPrivate");
+   FETCH_ATOM("XdndActionAsk");
+   FETCH_ATOM("XdndActionList");
+   FETCH_ATOM("XdndActionLink");
+   FETCH_ATOM("XdndActionDescription");
+   FETCH_ATOM("XdndProxy");
+   FETCH_ATOM("XdndStatus");
+   FETCH_ATOM("XdndLeave");
+   FETCH_ATOM("XdndDrop");
+   FETCH_ATOM("XdndFinished");
+
+   /* old E atom */
+   FETCH_ATOM("_E_FRAME_SIZE");
+
+   /* old Gnome atom */
+   FETCH_ATOM("_WIN_LAYER");
+
+   /* ICCCM */
+   FETCH_ATOM("WM_PROTOCOLS");
+   FETCH_ATOM("WM_COLORMAP_WINDOWS");
+
+   FETCH_ATOM("WM_STATE");
+
+   FETCH_ATOM("WM_CHANGE_STATE");
+
+   FETCH_ATOM("WM_TAKE_FOCUS");
+   FETCH_ATOM("WM_SAVE_YOURSELF");
+   FETCH_ATOM("WM_DELETE_WINDOW");
+
+   FETCH_ATOM("WM_COLORMAP_NOTIFY");
+
+   FETCH_ATOM("SM_CLIENT_ID");
+   FETCH_ATOM("WM_CLIENT_LEADER");
+   FETCH_ATOM("WM_WINDOW_ROLE");
+
+   /* Motif WM atom */
+   FETCH_ATOM("_MOTIF_WM_HINTS");
+
+   /* NetWM atoms */
+   FETCH_ATOM("_NET_SUPPORTED");
+   FETCH_ATOM("_NET_CLIENT_LIST");
+   FETCH_ATOM("_NET_CLIENT_LIST_STACKING");
+   FETCH_ATOM("_NET_NUMBER_OF_DESKTOPS");
+   FETCH_ATOM("_NET_DESKTOP_GEOMETRY");
+   FETCH_ATOM("_NET_DESKTOP_VIEWPORT");
+   FETCH_ATOM("_NET_CURRENT_DESKTOP");
+   FETCH_ATOM("_NET_DESKTOP_NAMES");
+   FETCH_ATOM("_NET_ACTIVE_WINDOW");
+   FETCH_ATOM("_NET_WORKAREA");
+   FETCH_ATOM("_NET_SUPPORTING_WM_CHECK");
+   FETCH_ATOM("_NET_VIRTUAL_ROOTS");
+   FETCH_ATOM("_NET_DESKTOP_LAYOUT");
+   FETCH_ATOM("_NET_SHOWING_DESKTOP");
+
+   FETCH_ATOM("_NET_CLOSE_WINDOW");
+   FETCH_ATOM("_NET_MOVERESIZE_WINDOW");
+   FETCH_ATOM("_NET_WM_MOVERESIZE");
+   FETCH_ATOM("_NET_RESTACK_WINDOW");
+   FETCH_ATOM("_NET_REQUEST_FRAME_EXTENTS");
+
+   FETCH_ATOM("_NET_WM_NAME");
+   FETCH_ATOM("_NET_WM_VISIBLE_NAME");
+   FETCH_ATOM("_NET_WM_ICON_NAME");
+   FETCH_ATOM("_NET_WM_VISIBLE_ICON_NAME");
+   FETCH_ATOM("_NET_WM_DESKTOP");
+
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_DESKTOP");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_DOCK");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_TOOLBAR");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_MENU");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_UTILITY");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_DIALOG");
+   FETCH_ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
+
+   FETCH_ATOM("_NET_WM_STATE");
+   FETCH_ATOM("_NET_WM_STATE_MODAL");
+   FETCH_ATOM("_NET_WM_STATE_STICKY");
+   FETCH_ATOM("_NET_WM_STATE_MAXIMIZED_VERT");
+   FETCH_ATOM("_NET_WM_STATE_MAXIMIZED_HORZ");
+   FETCH_ATOM("_NET_WM_STATE_SHADED");
+   FETCH_ATOM("_NET_WM_STATE_SKIP_TASKBAR");
+   FETCH_ATOM("_NET_WM_STATE_SKIP_PAGER");
+   FETCH_ATOM("_NET_WM_STATE_HIDDEN");
+   FETCH_ATOM("_NET_WM_STATE_FULLSCREEN");
+   FETCH_ATOM("_NET_WM_STATE_ABOVE");
+   FETCH_ATOM("_NET_WM_STATE_BELOW");
+   FETCH_ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
+
+   FETCH_ATOM("_NET_WM_ALLOWED_ACTIONS");
+   FETCH_ATOM("_NET_WM_ACTION_MOVE");
+   FETCH_ATOM("_NET_WM_ACTION_RESIZE");
+   FETCH_ATOM("_NET_WM_ACTION_MINIMIZE");
+   FETCH_ATOM("_NET_WM_ACTION_SHADE");
+   FETCH_ATOM("_NET_WM_ACTION_STICK");
+   FETCH_ATOM("_NET_WM_ACTION_MAXIMIZE_HORZ");
+   FETCH_ATOM("_NET_WM_ACTION_MAXIMIZE_VERT");
+   FETCH_ATOM("_NET_WM_ACTION_FULLSCREEN");
+   FETCH_ATOM("_NET_WM_ACTION_CHANGE_DESKTOP");
+   FETCH_ATOM("_NET_WM_ACTION_CLOSE");
+   FETCH_ATOM("_NET_WM_ACTION_ABOVE");
+   FETCH_ATOM("_NET_WM_ACTION_BELOW");
+
+   FETCH_ATOM("_NET_WM_STRUT");
+   FETCH_ATOM("_NET_WM_STRUT_PARTIAL");
+   FETCH_ATOM("_NET_WM_ICON_GEOMETRY");
+   FETCH_ATOM("_NET_WM_ICON");
+   FETCH_ATOM("_NET_WM_PID");
+   FETCH_ATOM("_NET_WM_HANDLED_ICONS");
+   FETCH_ATOM("_NET_WM_USER_TIME");
+   FETCH_ATOM("_NET_STARTUP_ID");
+   FETCH_ATOM("_NET_FRAME_EXTENTS");
+
+   FETCH_ATOM("_NET_WM_PING");
+   FETCH_ATOM("_NET_WM_SYNC_REQUEST");
+   FETCH_ATOM("_NET_WM_SYNC_REQUEST_COUNTER");
+
+   FETCH_ATOM("_NET_WM_WINDOW_OPACITY");
+   FETCH_ATOM("_NET_WM_WINDOW_SHADOW");
+   FETCH_ATOM("_NET_WM_WINDOW_SHADE");
+
+   FETCH_ATOM("_NET_STARTUP_INFO_BEGIN");
+   FETCH_ATOM("_NET_STARTUP_INFO");
+
+   /* selection atoms */
+   FETCH_ATOM("TARGETS");
+   FETCH_ATOM("CLIPBOARD");
+   FETCH_ATOM("_ECORE_SELECTION_PRIMARY");
+   FETCH_ATOM("_ECORE_SELECTION_SECONDARY");
+   FETCH_ATOM("_ECORE_SELECTION_CLIPBOARD");
+
+   /* These atoms are already internally defined */
+   ECORE_X_ATOM_SELECTION_PRIMARY   = 1;
+   ECORE_X_ATOM_SELECTION_SECONDARY = 2;
+   ECORE_X_ATOM_ATOM                = 4;
+   ECORE_X_ATOM_CARDINAL            = 6;
+   ECORE_X_ATOM_STRING              = 31;
+   ECORE_X_ATOM_WINDOW              = 33;
+   ECORE_X_ATOM_WM_NAME             = 39;
+   ECORE_X_ATOM_WM_ICON_NAME        = 37;
+   ECORE_X_ATOM_WM_NORMAL_HINTS     = 40;
+   ECORE_X_ATOM_WM_SIZE_HINTS       = 41;
+   ECORE_X_ATOM_WM_HINTS            = 35;
+   ECORE_X_ATOM_WM_CLASS            = 67;
+   ECORE_X_ATOM_WM_TRANSIENT_FOR    = 68;
+   ECORE_X_ATOM_WM_COMMAND          = 34;
+   ECORE_X_ATOM_WM_CLIENT_MACHINE   = 36;
+   ECORE_X_ATOM_WM_ICON_SIZE        = 38;
+
+   /* Initialize the globally defined xdnd atoms */
+   ECORE_X_DND_ACTION_COPY          = ECORE_X_ATOM_XDND_ACTION_COPY;
+   ECORE_X_DND_ACTION_MOVE          = ECORE_X_ATOM_XDND_ACTION_MOVE;
+   ECORE_X_DND_ACTION_LINK          = ECORE_X_ATOM_XDND_ACTION_LINK;
+   ECORE_X_DND_ACTION_ASK           = ECORE_X_ATOM_XDND_ACTION_ASK;
+   ECORE_X_DND_ACTION_PRIVATE       = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
+}
+
+void
+_ecore_x_atom_init_finalize(xcb_intern_atom_cookie_t *atom_cookies)
+{
+   xcb_intern_atom_reply_t *reply = NULL;
+   int i = 0;
+
+   /* generic atoms */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_COMPOUND_TEXT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_FILE_NAME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_TEXT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_UTF8_STRING);
+
+   /* dnd atoms */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_PROP_XDND);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_XDND);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_AWARE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ENTER);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_TYPE_LIST);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_POSITION);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_COPY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_MOVE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_PRIVATE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_ASK);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_LIST);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_LINK);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_ACTION_DESCRIPTION);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_PROXY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_STATUS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_LEAVE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_DROP);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_XDND_FINISHED);
+
+   /* old E atom */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_E_FRAME_SIZE);
+
+   /* old Gnome atom */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WIN_LAYER);
+
+   /* ICCCM */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_PROTOCOLS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_STATE);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_CHANGE_STATE);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_TAKE_FOCUS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_SAVE_YOURSELF);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_DELETE_WINDOW);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_COLORMAP_NOTIFY);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SM_CLIENT_ID);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_CLIENT_LEADER);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_WM_WINDOW_ROLE);
+
+   /* Motif WM atom */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_MOTIF_WM_HINTS);
+
+   /* NetWM atoms */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_SUPPORTED);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_CLIENT_LIST);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_CLIENT_LIST_STACKING);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_DESKTOP_GEOMETRY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_DESKTOP_VIEWPORT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_CURRENT_DESKTOP);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_DESKTOP_NAMES);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_ACTIVE_WINDOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WORKAREA);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_VIRTUAL_ROOTS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_DESKTOP_LAYOUT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_SHOWING_DESKTOP);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_CLOSE_WINDOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_MOVERESIZE_WINDOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_MOVERESIZE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_RESTACK_WINDOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_NAME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ICON_NAME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_DESKTOP);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_MODAL);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_STICKY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_SHADED);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_HIDDEN);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_ABOVE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_BELOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_MOVE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_RESIZE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_SHADE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_STICK);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_CLOSE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_ABOVE);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ACTION_BELOW);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STRUT);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_STRUT_PARTIAL);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ICON_GEOMETRY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_ICON);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_PID);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_HANDLED_ICONS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_USER_TIME);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_STARTUP_ID);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_FRAME_EXTENTS);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_PING);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_SYNC_REQUEST);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_OPACITY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_SHADOW);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_WM_WINDOW_SHADE);
+
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_NET_STARTUP_INFO);
+
+   /* selection atoms */
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_TARGETS);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_CLIPBOARD);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_PROP_PRIMARY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_PROP_SECONDARY);
+   FETCH_ATOM_FINALIZE(ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD);
+}
+
+
+/**
+ * Sends the InternAtom request.
+ * @param name Name of the requested atom.
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI void
+ecore_x_atom_get_prefetch(const char *name)
+{
+   xcb_intern_atom_cookie_t cookie;
+
+   cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(name), name);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the InternAtom request sent by ecore_x_atom_get_prefetch().
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI void
+ecore_x_atom_get_fetch(void)
+{
+   xcb_intern_atom_cookie_t cookie;
+   xcb_intern_atom_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieves the atom value associated to a name.
+ * @param  name Unused.
+ * @return      Associated atom value.
+ *
+ * Retrieves the atom value associated to a name. The reply is the
+ * returned value of the function ecore_xcb_intern_atom_reply(). If
+ * @p reply is @c NULL, the NULL atom is returned. Otherwise, the atom
+ * associated to the name is returned.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_atom_get_prefetch(), which sends the InternAtom request,
+ * then ecore_x_atom_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI Ecore_X_Atom
+ecore_x_atom_get(const char *name __UNUSED__)
+{
+   xcb_intern_atom_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return XCB_NONE;
+
+   return reply->atom;
+}
+
+
+/**
+ * Sends the GetAtomName request.
+ * @param atom Atom to get the name from.
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI void
+ecore_x_get_atom_name_prefetch(Ecore_X_Atom atom)
+{
+   xcb_get_atom_name_cookie_t cookie;
+
+   cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, atom);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetAtomName request sent by ecore_x_get_atom_name_prefetch().
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI void
+ecore_x_get_atom_name_fetch(void)
+{
+   xcb_get_atom_name_cookie_t cookie;
+   xcb_get_atom_name_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieves the name of the given atom.
+ * @param  atom Unused.
+ * @return      The name of the atom.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_atom_name_prefetch(), which sends the GetAtomName request,
+ * then ecore_x_get_atom_name_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Atom_Group
+ */
+EAPI char *
+ecore_x_atom_name_get(Ecore_X_Atom atom)
+{
+   xcb_get_atom_name_reply_t *reply;
+   char                      *name;
+   int                        length;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return NULL;
+
+   length = xcb_get_atom_name_name_length(reply);
+   name = (char *)malloc(sizeof(char) * (length + 1));
+   if (!name) return NULL;
+
+   memcpy(name, xcb_get_atom_name_name(reply), length);
+   name[length] = '\0';
+
+   return name;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_composite.c b/src/lib/ecore_x/xcb/ecore_xcb_composite.c
new file mode 100644 (file)
index 0000000..e2c9a21
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+/**
+ * @defgroup Ecore_X_Composite_Group X Composite Extension Functions
+ *
+ * Functions related to the X Composite extension.
+ */
+
+#ifdef ECORE_XCB_COMPOSITE
+static uint8_t _composite_available = 0;
+static xcb_composite_query_version_cookie_t _ecore_xcb_composite_init_cookie;
+#endif /* ECORE_XCB_COMPOSITE */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_composite_init and
+   _ecore_xcb_composite_init_finalize. The first one gets the cookies and
+   the second one gets the replies. */
+
+void
+_ecore_x_composite_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_COMPOSITE
+   if (reply && reply->present)
+      _ecore_xcb_composite_init_cookie = xcb_composite_query_version_unchecked(_ecore_xcb_conn, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION);
+#endif /* ECORE_XCB_COMPOSITE */
+}
+
+void
+_ecore_x_composite_init_finalize(void)
+{
+#ifdef ECORE_XCB_COMPOSITE
+   xcb_composite_query_version_reply_t *reply;
+
+   reply = xcb_composite_query_version_reply(_ecore_xcb_conn,
+                                          _ecore_xcb_composite_init_cookie,
+                                          NULL);
+   if (reply)
+     {
+        if ((reply->major_version == XCB_COMPOSITE_MAJOR_VERSION) &&
+           (reply->minor_version >= XCB_COMPOSITE_MINOR_VERSION))
+          _composite_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_COMPOSITE */
+}
+
+/**
+ * Return whether the Composite Extension is available.
+ * @return 1 if the Composite Extension is available, 0 if not.
+ *
+ * Return 1 if the X server supports the Composite Extension version 0.4
+ * or greater, 0 otherwise.
+ * @ingroup Ecore_X_Composite_Group
+ */
+EAPI int
+ecore_x_composite_query(void)
+{
+#ifdef ECORE_XCB_COMPOSITE
+   return _composite_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_COMPOSITE */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_cursor.c b/src/lib/ecore_x/xcb/ecore_xcb_cursor.c
new file mode 100644 (file)
index 0000000..1dcea4d
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+#include <xcb/shm.h>
+#include <xcb/xcb_image.h>
+
+
+extern int _ecore_xcb_xcursor;
+
+
+EAPI int
+ecore_x_cursor_color_supported_get(void)
+{
+   return _ecore_xcb_xcursor;
+}
+
+EAPI Ecore_X_Cursor
+ecore_x_cursor_new(Ecore_X_Window window,
+                   int           *pixels,
+                   int            w,
+                   int            h,
+                   int            hot_x,
+                   int            hot_y)
+{
+   Ecore_X_Cursor cursor = 0;
+
+#ifdef ECORE_XCB_CURSOR
+   if (_ecore_x_xcursor)
+     {
+       Cursor c;
+       XcursorImage *xci;
+
+       xci = XcursorImageCreate(w, h);
+       if (xci)
+         {
+            int i;
+
+            xci->xhot = hot_x;
+            xci->yhot = hot_y;
+            xci->delay = 0;
+            for (i = 0; i < (w * h); i++)
+              {
+//               int r, g, b, a;
+//
+//               a = (pixels[i] >> 24) & 0xff;
+//               r = (((pixels[i] >> 16) & 0xff) * a) / 0xff;
+//               g = (((pixels[i] >> 8 ) & 0xff) * a) / 0xff;
+//               b = (((pixels[i]      ) & 0xff) * a) / 0xff;
+                 xci->pixels[i] = pixels[i];
+//                 (a << 24) | (r << 16) | (g << 8) | (b);
+              }
+            c = XcursorImageLoadCursor(_ecore_x_disp, xci);
+            XcursorImageDestroy(xci);
+            return c;
+         }
+     }
+   else
+#endif /* ECORE_XCB_CURSOR */
+     {
+       const uint32_t dither[2][2] =
+         {
+              {0, 2},
+              {3, 1}
+         };
+        Ecore_X_Drawable draw;
+        Ecore_X_Pixmap   pixmap;
+        Ecore_X_Pixmap   mask;
+        Ecore_X_GC       gc;
+        xcb_image_t     *image;
+        uint32_t        *pix;
+        uint8_t          fr;
+        uint8_t          fg;
+        uint8_t          fb;
+        uint8_t          br;
+        uint8_t          bg;
+        uint8_t          bb;
+       uint32_t         brightest = 0;
+       uint32_t         darkest = 255 * 3;
+        uint16_t         x;
+        uint16_t         y;
+
+        draw = window;
+        pixmap = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_pixmap(_ecore_xcb_conn,
+                          1, pixmap, draw,
+                          1, 1);
+        mask = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_pixmap(_ecore_xcb_conn,
+                          1, mask, draw,
+                          1, 1);
+
+        image = xcb_image_create_native(_ecore_xcb_conn, w, h,
+                                 XCB_IMAGE_FORMAT_Z_PIXMAP,
+                                 32, NULL, ~0, NULL);
+        image->data = malloc(image->size);
+
+       fr = 0x00; fg = 0x00; fb = 0x00;
+       br = 0xff; bg = 0xff; bb = 0xff;
+        pix = (uint32_t *)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 uint8_t r, g, b, a;
+
+                 a = (pix[0] >> 24) & 0xff;
+                 r = (pix[0] >> 16) & 0xff;
+                 g = (pix[0] >> 8 ) & 0xff;
+                 b = (pix[0]      ) & 0xff;
+                 if (a > 0)
+                   {
+                      if ((uint32_t)(r + g + b) > brightest)
+                        {
+                           brightest = r + g + b;
+                           br = r;
+                           bg = g;
+                           bb = b;
+                        }
+                      if ((uint32_t)(r + g + b) < darkest)
+                        {
+                           darkest = r + g + b;
+                           fr = r;
+                           fg = g;
+                           fb = b;
+                        }
+                   }
+                 pix++;
+              }
+         }
+
+       pix = (uint32_t *)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 uint32_t v;
+                 uint8_t  r, g, b;
+                 int32_t  d1, d2;
+
+                 r = (pix[0] >> 16) & 0xff;
+                 g = (pix[0] >> 8 ) & 0xff;
+                 b = (pix[0]      ) & 0xff;
+                 d1 =
+                   ((r - fr) * (r - fr)) +
+                   ((g - fg) * (g - fg)) +
+                   ((b - fb) * (b - fb));
+                 d2 =
+                   ((r - br) * (r - br)) +
+                   ((g - bg) * (g - bg)) +
+                   ((b - bb) * (b - bb));
+                 if (d1 + d2)
+                   {
+                      v = (((d2 * 255) / (d1 + d2)) * 5) / 256;
+                      if (v > dither[x & 0x1][y & 0x1]) v = 1;
+                      else v = 0;
+                   }
+                 else
+                   {
+                      v = 0;
+                   }
+                 xcb_image_put_pixel(image, x, y, v);
+                 pix++;
+              }
+         }
+        draw = pixmap;
+        gc = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_gc(_ecore_xcb_conn, gc, draw, 0, NULL);
+        xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0);
+        xcb_free_gc(_ecore_xcb_conn, gc);
+
+       pix = (uint32_t *)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 uint32_t v;
+
+                 v = (((pix[0] >> 24) & 0xff) * 5) / 256;
+                 if (v > dither[x & 0x1][y & 0x1]) v = 1;
+                 else v = 0;
+                 xcb_image_put_pixel(image, x, y, v);
+                 pix++;
+              }
+         }
+        draw = mask;
+        gc = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL);
+        xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0);
+        xcb_free_gc(_ecore_xcb_conn, gc);
+
+       free(image->data);
+       image->data = NULL;
+       xcb_image_destroy(image);
+
+        cursor = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_cursor (_ecore_xcb_conn, cursor,
+                           pixmap, mask,
+                           fr << 8 | fr,
+                           fg << 8 | fg,
+                           fb << 8 | fb,
+                           br << 8 | br,
+                           bg << 8 | bg,
+                           bb << 8 | bb,
+                           hot_x,
+                           hot_y);
+       xcb_free_pixmap(_ecore_xcb_conn, pixmap);
+       xcb_free_pixmap(_ecore_xcb_conn, mask);
+
+       return cursor;
+     }
+   return 0;
+}
+
+EAPI void
+ecore_x_cursor_free(Ecore_X_Cursor cursor)
+{
+   xcb_free_cursor(_ecore_xcb_conn, cursor);
+}
+
+/*
+ * Returns the cursor for the given shape.
+ * Note that the return value must not be freed with
+ * ecore_x_cursor_free()!
+ */
+EAPI Ecore_X_Cursor
+ecore_x_cursor_shape_get(int shape)
+{
+   Ecore_X_Cursor cursor;
+   xcb_font_t     font;
+
+   /* Shapes are defined in Ecore_X_Cursor.h */
+   font = xcb_generate_id(_ecore_xcb_conn);
+   xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor");
+
+   cursor = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_glyph_cursor (_ecore_xcb_conn,
+                            cursor,
+                            font,
+                            font,
+                            shape,
+                            shape + 1,
+                            0, 0, 0,
+                            65535, 65535, 65535);
+
+   xcb_close_font(_ecore_xcb_conn, font);
+
+   return cursor;
+}
+
+EAPI void
+ecore_x_cursor_size_set(int size)
+{
+#ifdef ECORE_XCB_CURSOR
+   XcursorSetDefaultSize(_ecore_x_disp, size);
+#else
+   size = 0;
+#endif /* ECORE_XCB_CURSOR */
+}
+
+EAPI int
+ecore_x_cursor_size_get(void)
+{
+#ifdef ECORE_XCB_CURSOR
+   return XcursorGetDefaultSize(_ecore_x_disp);
+#else
+   return 0;
+#endif /* ECORE_XCB_CURSOR */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_damage.c b/src/lib/ecore_x/xcb/ecore_xcb_damage.c
new file mode 100644 (file)
index 0000000..6e104b3
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Damage_Group X Damage Extension Functions
+ *
+ * Functions related to the X Damage extension.
+ */
+
+
+#ifdef ECORE_XCB_DAMAGE
+static uint8_t _damage_available = 0;
+static xcb_damage_query_version_cookie_t _ecore_xcb_damage_init_cookie;
+#endif /* ECORE_XCB_DAMAGE */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_damage_init and
+   _ecore_xcb_damage_init_finalize. The first one gets the cookies and
+   the second one gets the replies. */
+
+void
+_ecore_x_damage_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_DAMAGE
+   if (reply && (reply->present))
+      _ecore_xcb_damage_init_cookie = xcb_damage_query_version_unchecked(_ecore_xcb_conn, 1, 1);
+#endif /* ECORE_XCB_DAMAGE */
+}
+
+void
+_ecore_x_damage_init_finalize(void)
+{
+#ifdef ECORE_XCB_DAMAGE
+   xcb_damage_query_version_reply_t *reply;
+
+   reply = xcb_damage_query_version_reply(_ecore_xcb_conn,
+                                          _ecore_xcb_damage_init_cookie,
+                                          NULL);
+   if (reply)
+     {
+        if (reply->major_version >= 1)
+          _damage_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_DAMAGE */
+}
+
+
+/**
+ * Return whether the Damage Extension is available.
+ * @return 1 if the Damage Extension is available, 0 if not.
+ *
+ * Return 1 if the X server supports the Damage Extension version 1.0,
+ * 0 otherwise.
+ * @ingroup Ecore_X_Damage_Group
+ */
+EAPI int
+ecore_x_damage_query(void)
+{
+#ifdef ECORE_XCB_DAMAGE
+   return _damage_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_DAMAGE */
+}
+
+
+/**
+ * Creates a damage object.
+ * @param drawable The drawable to monotor.
+ * @param level    The level of the damage report.
+ * @return         The damage object.
+ *
+ * Creates a damage object to monitor changes to @p drawable, with the
+ * level @p level.
+ * @ingroup Ecore_X_Damage_Group
+ */
+EAPI Ecore_X_Damage
+ecore_x_damage_new(Ecore_X_Drawable            drawable,
+                   Ecore_X_Damage_Report_Level level)
+{
+   Ecore_X_Damage damage = 0;
+
+#ifdef ECORE_XCB_DAMAGE
+   damage = xcb_generate_id(_ecore_xcb_conn);
+   xcb_damage_create(_ecore_xcb_conn, damage, drawable, level);
+#endif /* ECORE_XCB_DAMAGE */
+
+   return damage;
+}
+
+
+/**
+ * Destroys a damage object.
+ * @param damage The damage object to destroy.
+ *
+ * Destroys the damage object @p damage.
+ * @ingroup Ecore_X_Damage_Group
+ */
+EAPI void
+ecore_x_damage_free(Ecore_X_Damage damage)
+{
+#ifdef ECORE_XCB_DAMAGE
+   xcb_damage_destroy(_ecore_xcb_conn, damage);
+#endif /* ECORE_XCB_DAMAGE */
+}
+
+
+/**
+ * Synchronously modifies the region.
+ * @param damage The damage object to destroy.
+ * @param repair The repair region.
+ * @param parts  The parts region.
+ *
+ * Synchronously modifies the regions in the following manner:
+ * If @p repair is @c XCB_NONE:
+ *   1) parts = damage
+ *   2) damage = <empty>
+ * Otherwise:
+ *   1) parts = damage INTERSECT repair
+ *   2) damage = damage - parts
+ *   3) Generate DamageNotify for remaining damage areas
+ * @ingroup Ecore_X_Damage_Group
+ */
+EAPI void
+ecore_x_damage_subtract(Ecore_X_Damage damage,
+                        Ecore_X_Region repair,
+                        Ecore_X_Region parts)
+{
+#ifdef ECORE_XCB_DAMAGE
+   xcb_damage_subtract(_ecore_xcb_conn, damage, repair, parts);
+#endif /* ECORE_XCB_DAMAGE */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_dnd.c b/src/lib/ecore_x/xcb/ecore_xcb_dnd.c
new file mode 100644 (file)
index 0000000..dfa5562
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+EAPI int ECORE_X_EVENT_XDND_ENTER    = 0;
+EAPI int ECORE_X_EVENT_XDND_POSITION = 0;
+EAPI int ECORE_X_EVENT_XDND_STATUS   = 0;
+EAPI int ECORE_X_EVENT_XDND_LEAVE    = 0;
+EAPI int ECORE_X_EVENT_XDND_DROP     = 0;
+EAPI int ECORE_X_EVENT_XDND_FINISHED = 0;
+
+static Ecore_X_DND_Source *_source = NULL;
+static Ecore_X_DND_Target *_target = NULL;
+static int _ecore_x_dnd_init_count = 0;
+
+
+void
+_ecore_x_dnd_init(void)
+{
+   if (!_ecore_x_dnd_init_count)
+     {
+
+       _source = calloc(1, sizeof(Ecore_X_DND_Source));
+       _source->version = ECORE_X_DND_VERSION;
+       _source->win = XCB_NONE;
+       _source->dest = XCB_NONE;
+       _source->state = ECORE_X_DND_SOURCE_IDLE;
+       _source->prev.window = 0;
+
+       _target = calloc(1, sizeof(Ecore_X_DND_Target));
+       _target->win = XCB_NONE;
+       _target->source = XCB_NONE;
+       _target->state = ECORE_X_DND_TARGET_IDLE;
+
+       ECORE_X_EVENT_XDND_ENTER    = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_POSITION = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_STATUS   = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_LEAVE    = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_DROP     = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_FINISHED = ecore_event_type_new();
+     }
+
+   _ecore_x_dnd_init_count++;
+}
+
+void
+_ecore_x_dnd_shutdown(void)
+{
+   _ecore_x_dnd_init_count--;
+   if (_ecore_x_dnd_init_count > 0)
+     return;
+
+   if (_source)
+     free(_source);
+   _source = NULL;
+
+   if (_target)
+     free(_target);
+   _target = NULL;
+
+   _ecore_x_dnd_init_count = 0;
+}
+
+EAPI void
+ecore_x_dnd_aware_set(Ecore_X_Window window,
+                      int            on)
+{
+   Ecore_X_Atom prop_data = ECORE_X_DND_VERSION;
+
+   if (on)
+     ecore_x_window_prop_property_set(window, ECORE_X_ATOM_XDND_AWARE,
+                                     ECORE_X_ATOM_ATOM, 32, &prop_data, 1);
+   else
+     ecore_x_window_prop_property_del(window, ECORE_X_ATOM_XDND_AWARE);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ */
+EAPI void
+ecore_x_dnd_version_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_XDND_AWARE,
+                                       ECORE_X_ATOM_ATOM,
+                                       0, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_dnd_version_get_prefetch().
+ */
+EAPI void
+ecore_x_dnd_version_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the DnD version.
+ * @param  window Unused.
+ * @return        0 on failure, the version otherwise.
+ *
+ * Get the DnD version. Returns 0 on failure, the version otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dnd_version_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_dnd_version_get_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_dnd_version_get(Ecore_X_Window window)
+{
+   unsigned char            *prop_data;
+   int                       num;
+
+   if (ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_AWARE,
+                                        ECORE_X_ATOM_ATOM, 32, &prop_data, &num))
+     {
+       int version = (int) *prop_data;
+       free(prop_data);
+       return version;
+     }
+   else
+     return 0;
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ */
+EAPI void
+ecore_x_dnd_type_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_XDND_TYPE_LIST,
+                                       ECORE_X_ATOM_ATOM,
+                                       0, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_dnd_type_get_prefetch().
+ */
+EAPI void
+ecore_x_dnd_type_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/* FIXME: round trip (InternAtomGet request) */
+
+/**
+ * Check if the type is set.
+ * @param   window Unused.
+ * @param   type   The type to check
+ * @return         0 on failure, 1 otherwise.
+ *
+ * Check if the type is set. 0 on failure, 1 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_dnd_type_get_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_dnd_type_isset(Ecore_X_Window window,
+                       const char    *type)
+{
+   xcb_intern_atom_cookie_t cookie;
+   xcb_intern_atom_reply_t *reply;
+   Ecore_X_Atom            *atoms;
+   unsigned char           *data;
+   int                      num;
+   int                      i;
+   uint8_t                  ret = 0;
+
+   cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
+                                      strlen(type), type);
+
+   if (!ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                        ECORE_X_ATOM_ATOM, 32, &data, &num))
+     {
+        reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+        if (reply) free(reply);
+        return ret;
+     }
+
+   reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply)
+     {
+        free(data);
+        return 0;
+     }
+   atoms = (Ecore_X_Atom *)data;
+
+   for (i = 0; i < num; ++i)
+     {
+       if (reply->atom == atoms[i])
+         {
+            ret = 1;
+            break;
+         }
+     }
+
+   free(data);
+   free(reply);
+
+   return ret;
+}
+
+/* FIXME: round trip (InternAtomGet request) */
+
+/**
+ * Set the type.
+ * @param   window Unused.
+ * @param   type   The type to set
+ * @param   on     0 or non 0...
+ *
+ * Set the type.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_dnd_type_get_fetch(), which gets the reply.
+ */
+EAPI void
+ecore_x_dnd_type_set(Ecore_X_Window window,
+                     const char    *type,
+                     int            on)
+{
+   xcb_intern_atom_cookie_t cookie;
+   xcb_intern_atom_reply_t *reply;
+   Ecore_X_Atom            *oldset = NULL;
+   Ecore_X_Atom            *newset = NULL;
+   unsigned char           *data = NULL;
+   unsigned char           *old_data = NULL;
+   Ecore_X_Atom             atom;
+   int                      i, j = 0, num = 0;
+
+   cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
+                                      strlen(type), type);
+
+   atom = ecore_x_atom_get(type);
+   if (!ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                         ECORE_X_ATOM_ATOM,
+                                         32, &old_data, &num))
+     {
+        reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+        if (reply) free(reply);
+        return;
+     }
+   oldset = (Ecore_X_Atom *)old_data;
+
+   if (on)
+     {
+       if (ecore_x_dnd_type_isset(window, type))
+         {
+            free(old_data);
+             reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+             if (reply) free(reply);
+            return;
+         }
+       data = calloc(num + 1, sizeof(Ecore_X_Atom));
+       if (!data)
+          {
+            free(old_data);
+             reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+             if (reply) free(reply);
+             return;
+          }
+       newset = (Ecore_X_Atom *)data;
+
+       for (i = 0; i < num; i++)
+         newset[i + 1] = oldset[i];
+       /* prepend the new type */
+
+        reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+        if (!reply)
+          {
+            free(old_data);
+            return;
+          }
+       newset[0] = reply->atom;
+        free(reply);
+
+       ecore_x_window_prop_property_set(window,
+                                         ECORE_X_ATOM_XDND_TYPE_LIST,
+                                         ECORE_X_ATOM_ATOM,
+                                         32, data, num + 1);
+     }
+   else
+     {
+       if (!ecore_x_dnd_type_isset(window, type))
+         {
+            free(old_data);
+            return;
+         }
+       newset = calloc(num - 1, sizeof(Ecore_X_Atom));
+       if (!newset)
+         {
+            free(old_data);
+            return;
+         }
+       data = (unsigned char *)newset;
+       for (i = 0; i < num; i++)
+         if (oldset[i] != atom)
+           newset[j++] = oldset[i];
+
+       ecore_x_window_prop_property_set(window,
+                                         ECORE_X_ATOM_XDND_TYPE_LIST,
+                                         ECORE_X_ATOM_ATOM,
+                                         32, data, num - 1);
+     }
+
+   free(oldset);
+   free(newset);
+}
+
+/* FIXME: round trips, but I don't think we can do much, here */
+
+/**
+ * Set the types.
+ * @param   window Unused.
+ * @param   types  The types to set
+ * @param   num_types The number of types
+ *
+ * Set the types.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_dnd_type_get_fetch(), which gets the reply.
+ */
+EAPI void
+ecore_x_dnd_types_set(Ecore_X_Window window,
+                      const char   **types,
+                      unsigned int   num_types)
+{
+   Ecore_X_Atom *newset = NULL;
+   void         *data = NULL;
+   uint32_t      i;
+
+   if (!num_types)
+     {
+       ecore_x_window_prop_property_del(window, ECORE_X_ATOM_XDND_TYPE_LIST);
+     }
+   else
+     {
+        xcb_intern_atom_cookie_t *cookies;
+        xcb_intern_atom_reply_t  *reply;
+
+        cookies = (xcb_intern_atom_cookie_t *)malloc(sizeof(xcb_intern_atom_cookie_t));
+        if (!cookies) return;
+       for (i = 0; i < num_types; i++)
+         cookies[i] = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
+                                                 strlen(types[i]), types[i]);
+        data = calloc(num_types, sizeof(Ecore_X_Atom));
+       if (!data)
+          {
+            for (i = 0; i < num_types; i++)
+              {
+                 reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], NULL);
+                 if (reply) free(reply);
+              }
+            free(cookies);
+            return;
+          }
+       newset = data;
+       for (i = 0; i < num_types; i++)
+          {
+             reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], NULL);
+             if (reply)
+               {
+                  newset[i] = reply->atom;
+                  free(reply);
+               }
+             else
+               newset[i] = XCB_NONE;
+          }
+        free(cookies);
+       ecore_x_window_prop_property_set(window, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                         ECORE_X_ATOM_ATOM, 32, data, num_types);
+       free(data);
+     }
+}
+
+Ecore_X_DND_Source *
+_ecore_x_dnd_source_get(void)
+{
+   return _source;
+}
+
+Ecore_X_DND_Target *
+_ecore_x_dnd_target_get(void)
+{
+   return _target;
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param source Window whose properties are requested.
+ */
+EAPI void
+ecore_x_dnd_begin_prefetch(Ecore_X_Window source)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       source ? source : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_XDND_AWARE,
+                                       ECORE_X_ATOM_ATOM,
+                                       0, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_dnd_begin_prefetch().
+ */
+EAPI void
+ecore_x_dnd_begin_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/* FIXME: round trip */
+
+/**
+ * Begins the DnD.
+ * @param  source Unused.
+ * @param  data   The data.
+ * @param  size   The size of the data.
+ * @return        0 on failure, 1 otherwise.
+ *
+ * Begins the DnD. Returns 0 on failure, 1 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dnd_begin_prefetch(), which sends the GetProperty request,
+ * then ecore_x_dnd_begin_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_dnd_begin(Ecore_X_Window source,
+                  unsigned char *data,
+                  int            size)
+{
+   ecore_x_selection_xdnd_prefetch();
+   if (!ecore_x_dnd_version_get(source))
+     {
+        ecore_x_selection_xdnd_fetch();
+        return 0;
+     }
+
+   /* Take ownership of XdndSelection */
+   ecore_x_selection_xdnd_prefetch();
+   ecore_x_selection_xdnd_fetch();
+   if (!ecore_x_selection_xdnd_set(source, data, size))
+     return 0;
+
+   _source->win = source;
+   ecore_x_window_ignore_set(_source->win, 1);
+   _source->state = ECORE_X_DND_SOURCE_DRAGGING;
+   _source->time = _ecore_xcb_event_last_time;
+   _source->prev.window = 0;
+
+   /* Default Accepted Action: ask */
+   _source->action = ECORE_X_ATOM_XDND_ACTION_COPY;
+   _source->accepted_action = XCB_NONE;
+   return 1;
+}
+
+EAPI int
+ecore_x_dnd_drop(void)
+{
+   uint8_t status = 0;
+
+   if (_source->dest)
+     {
+        xcb_client_message_event_t ev;
+
+       ev.response_type = XCB_CLIENT_MESSAGE;
+       ev.format = 32;
+       ev.window = _source->dest;
+
+       if (_source->will_accept)
+         {
+            ev.type = ECORE_X_ATOM_XDND_DROP;
+            ev.data.data32[0] = _source->win;
+            ev.data.data32[1] = 0;
+            ev.data.data32[2] = _source->time;
+            xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev);
+            _source->state = ECORE_X_DND_SOURCE_DROPPED;
+            status = 1;
+         }
+       else
+         {
+            ev.type = ECORE_X_ATOM_XDND_LEAVE;
+            ev.data.data32[0] = _source->win;
+            ev.data.data32[1] = 0;
+            xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev);
+            _source->state = ECORE_X_DND_SOURCE_IDLE;
+         }
+     }
+   else
+     {
+       /* Dropping on nothing */
+       ecore_x_selection_xdnd_clear();
+       _source->state = ECORE_X_DND_SOURCE_IDLE;
+     }
+   ecore_x_window_ignore_set(_source->win, 0);
+
+   _source->prev.window = 0;
+   _source->dest = XCB_NONE;
+
+   return status;
+}
+
+EAPI void
+ecore_x_dnd_send_status(int               will_accept,
+                        int               suppress,
+                        Ecore_X_Rectangle rectangle,
+                        Ecore_X_Atom      action)
+{
+   xcb_client_message_event_t ev;
+
+   if (_target->state == ECORE_X_DND_TARGET_IDLE)
+     return;
+
+   _target->will_accept = will_accept;
+
+   ev.response_type = XCB_CLIENT_MESSAGE;
+   ev.format = 32;
+   ev.window = _target->source;
+   ev.type = ECORE_X_ATOM_XDND_STATUS;
+
+   ev.data.data32[0] = _target->win;
+   ev.data.data32[1] = 0;
+   if (will_accept)
+     ev.data.data32[1] |= 0x1UL;
+   if (!suppress)
+     ev.data.data32[1] |= 0x2UL;
+
+   /* Set rectangle information */
+   ev.data.data32[2] = rectangle.x;
+   ev.data.data32[2] <<= 16;
+   ev.data.data32[2] |= rectangle.y;
+   ev.data.data32[3] = rectangle.width;
+   ev.data.data32[3] <<= 16;
+   ev.data.data32[3] |= rectangle.height;
+
+   if (will_accept)
+     {
+       ev.data.data32[4] = action;
+       _target->accepted_action = action;
+     }
+   else
+     {
+       ev.data.data32[4] = XCB_NONE;
+       _target->accepted_action = action;
+     }
+
+   xcb_send_event(_ecore_xcb_conn, 0, _target->source, 0, (const char *)&ev);
+}
+
+EAPI void
+ecore_x_dnd_send_finished(void)
+{
+   xcb_client_message_event_t ev;
+
+   if (_target->state == ECORE_X_DND_TARGET_IDLE)
+     return;
+
+   ev.response_type = XCB_CLIENT_MESSAGE;
+   ev.format = 32;
+   ev.window = _target->source;
+   ev.type = ECORE_X_ATOM_XDND_FINISHED;
+
+   ev.data.data32[0] = _target->win;
+   ev.data.data32[1] = 0;
+   ev.data.data32[2] = 0;
+   if (_target->will_accept)
+     {
+       ev.data.data32[1] |= 0x1UL;
+       ev.data.data32[2] = _target->accepted_action;
+     }
+   xcb_send_event(_ecore_xcb_conn, 0, _target->source, 0, (const char *)&ev);
+
+   _target->state = ECORE_X_DND_TARGET_IDLE;
+}
+
+void
+ecore_x_dnd_source_action_set(Ecore_X_Atom action)
+{
+   _source->action = action;
+   if (_source->prev.window)
+     _ecore_x_dnd_drag(_source->prev.window, _source->prev.x, _source->prev.y);
+}
+
+Ecore_X_Atom
+ecore_x_dnd_source_action_get(void)
+{
+   return _source->action;
+}
+
+void
+_ecore_x_dnd_drag(Ecore_X_Window root,
+                 int x,
+                  int y)
+{
+   xcb_client_message_event_t ev;
+   Ecore_X_Window             win;
+   Ecore_X_Window            *skip;
+   int                        num;
+
+   if (_source->state != ECORE_X_DND_SOURCE_DRAGGING)
+     return;
+
+   ev.response_type = XCB_CLIENT_MESSAGE;
+   ev.format = 32;
+
+   /* Attempt to find a DND-capable window under the cursor */
+   skip = ecore_x_window_ignore_list(&num);
+//   win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
+   win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num);
+   while (win)
+     {
+        xcb_query_tree_cookie_t cookie_tree;
+        xcb_query_tree_reply_t *reply_tree;
+
+        ecore_x_dnd_version_get_prefetch(win);
+        cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, win);
+
+        ecore_x_dnd_version_get_fetch();
+        /* We found the correct window ? */
+        if (ecore_x_dnd_version_get(win))
+          {
+             reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+             if (reply_tree) free(reply_tree);
+             break;
+          }
+        reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+        if (reply_tree)
+          {
+            win = reply_tree->parent;
+            free(reply_tree);
+          }
+     }
+
+   /* Send XdndLeave to current destination window if we have left it */
+   if ((_source->dest) && (win != _source->dest))
+     {
+       ev.window = _source->dest;
+       ev.type = ECORE_X_ATOM_XDND_LEAVE;
+       ev.data.data32[0] = _source->win;
+       ev.data.data32[1] = 0;
+
+       xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev);
+       _source->suppress = 0;
+     }
+
+   if (win)
+     {
+       int16_t                   x1;
+       int16_t                   x2;
+       int16_t                   y1;
+       int16_t                   y2;
+
+        ecore_x_dnd_version_get_prefetch(win);
+        ecore_x_dnd_type_get_prefetch(_source->win);
+
+        ecore_x_dnd_version_get_fetch();
+        if (!ecore_x_dnd_version_get(win))
+          {
+            ecore_x_dnd_type_get_fetch();
+            return;
+          }
+
+       _source->version = MIN(ECORE_X_DND_VERSION,
+                               ecore_x_dnd_version_get(win));
+       if (win != _source->dest)
+         {
+            unsigned char *data;
+            Ecore_X_Atom  *types;
+            int            num;
+            int            i;
+
+             ecore_x_dnd_type_get_fetch();
+             if (!ecore_x_window_prop_property_get(_source->win,
+                                                   ECORE_X_ATOM_XDND_TYPE_LIST,
+                                                   ECORE_X_ATOM_ATOM,
+                                                   32, &data, &num))
+               return;
+
+            types = (Ecore_X_Atom *)data;
+
+            /* Entered new window, send XdndEnter */
+            ev.window = win;
+            ev.type = ECORE_X_ATOM_XDND_ENTER;
+            ev.data.data32[0] = _source->win;
+            ev.data.data32[1] = 0;
+            if (num > 3)
+              ev.data.data32[1] |= 0x1UL;
+            else
+              ev.data.data32[1] &= 0xfffffffeUL;
+            ev.data.data32[1] |= ((unsigned long) _source->version) << 24;
+
+            for (i = 2; i < 5; i++)
+              ev.data.data32[i] = 0;
+            for (i = 0; i < MIN(num, 3); ++i)
+              ev.data.data32[i + 2] = types[i];
+            free(data);
+            xcb_send_event(_ecore_xcb_conn, 0, win, 0, (const char *)&ev);
+            _source->await_status = 0;
+            _source->will_accept = 0;
+         }
+        else
+          ecore_x_dnd_type_get_fetch();
+
+       /* Determine if we're still in the rectangle from the last status */
+       x1 = _source->rectangle.x;
+       x2 = _source->rectangle.x + _source->rectangle.width;
+       y1 = _source->rectangle.y;
+       y2 = _source->rectangle.y + _source->rectangle.height;
+
+       if ((!_source->await_status) ||
+           (!_source->suppress) ||
+           ((x < x1) || (x > x2) || (y < y1) || (y > y2)))
+         {
+            ev.window = win;
+            ev.type = ECORE_X_ATOM_XDND_POSITION;
+            ev.data.data32[0] = _source->win;
+            ev.data.data32[1] = 0; /* Reserved */
+            ev.data.data32[2] = ((x << 16) & 0xffff0000) | (y & 0xffff);
+            ev.data.data32[3] = _source->time; /* Version 1 */
+            ev.data.data32[4] = _source->action; /* Version 2, Needs to be pre-set */
+            xcb_send_event(_ecore_xcb_conn, 0, win, 0, (const char *)&ev);
+
+            _source->await_status = 1;
+         }
+     }
+
+   _source->prev.x = x;
+   _source->prev.y = y;
+   _source->prev.window = root;
+   _source->dest = win;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_dpms.c b/src/lib/ecore_x/xcb/ecore_xcb_dpms.c
new file mode 100644 (file)
index 0000000..cb61d45
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_DPMS_Group X DPMS Extension Functions
+ *
+ * Functions related to the X DPMS extension.
+ */
+
+
+#ifdef ECORE_XCB_DPMS
+static int _dpms_available = 0;
+static xcb_dpms_get_version_cookie_t _ecore_xcb_dpms_init_cookie;
+#endif /* ECORE_XCB_DPMS */
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_dpms_init and
+   _ecore_xcb_dpms_init_finalize. The first one gets the cookies and
+   the second one gets the replies. */
+
+void
+_ecore_x_dpms_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_DPMS
+   if (reply && (reply->present))
+      _ecore_xcb_dpms_init_cookie = xcb_dpms_get_version_unchecked(_ecore_xcb_conn, 0, 0);
+#endif /* ECORE_XCB_DPMS */
+}
+
+void
+_ecore_x_dpms_init_finalize(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_version_reply_t *reply;
+
+   reply = xcb_dpms_get_version_reply(_ecore_xcb_conn,
+                                      _ecore_xcb_dpms_init_cookie, NULL);
+
+   if (reply)
+     {
+        if (reply->server_major_version >= 1)
+          _dpms_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Checks if the DPMS extension is available or not.
+ * @return @c 1 if the DPMS extension is available, @c 0 otherwise.
+ *
+ * Return 1 if the X server supports the DPMS Extension version 1.0,
+ * 0 otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_query(void)
+{
+#ifdef ECORE_XCB_DPMS
+   return _dpms_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Sends the DPMSCapable request.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_capable_get_prefetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_capable_cookie_t cookie;
+
+   cookie = xcb_dpms_capable_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Gets the reply of the DPMSCapable request sent by ecore_x_dpms_capable_get_prefetch().
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_capable_get_fetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_capable_cookie_t cookie;
+   xcb_dpms_capable_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_dpms_capable_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Checks if the X server is capable of DPMS.
+ * @return @c 1 if the X server is capable of DPMS, @c 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_capable_get_prefetch(), which sends the DPMSCapable request,
+ * then ecore_x_dpms_capable_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_capable_get(void)
+{
+   int                       capable = 0;
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_capable_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   capable = reply->capable;
+#endif /* ECORE_XCB_DPMS */
+
+   return capable;
+}
+
+
+/**
+ * Sends the DPMSInfo request.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_enable_get_prefetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_info_cookie_t cookie;
+
+   cookie = xcb_dpms_info_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Gets the reply of the DPMSInfo request sent by ecore_x_dpms_enable_get_prefetch().
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_enable_get_fetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_info_cookie_t cookie;
+   xcb_dpms_info_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_dpms_info_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Checks the DPMS state of the display.
+ * @return @c 1 if DPMS is enabled, @c 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_enapable_get_prefetch(), which sends the DPMSInfo request,
+ * then ecore_x_dpms_enapable_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_enable_get(void)
+{
+   int                    enable = 0;
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_info_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   enable = reply->state;
+#endif /* ECORE_XCB_DPMS */
+
+   return enable;
+}
+
+
+/**
+ * Sets the DPMS state of the display.
+ * @param enabled @c 0 to disable DPMS characteristics of the server, enable it otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_enabled_set(int enabled)
+{
+#ifdef ECORE_XCB_DPMS
+   if (enabled)
+      xcb_dpms_enable(_ecore_xcb_conn);
+   else
+      xcb_dpms_disable(_ecore_xcb_conn);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Sets the timeouts. The values are in unit of seconds.
+ * @param standby Amount of time of inactivity before standby mode will be invoked.
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ * @return        Returns always 1.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_timeouts_set(unsigned int standby,
+                          unsigned int suspend,
+                          unsigned int off)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_set_timeouts(_ecore_xcb_conn, standby, suspend, off);
+#endif /* ECORE_XCB_DPMS */
+
+   return 1;
+}
+
+
+/**
+ * Sends the DPMSGetTimeouts request.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeouts_get_prefetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_cookie_t cookie;
+
+   cookie = xcb_dpms_get_timeouts_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Gets the reply of the DPMSGetTimeouts request sent by ecore_x_dpms_timeouts_get_prefetch().
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeouts_get_fetch(void)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_cookie_t cookie;
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_dpms_get_timeouts_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Gets the timeouts. The values are in unit of seconds.
+ * @param standby Amount of time of inactivity before standby mode will be invoked.
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeouts_get(unsigned int *standby,
+                          unsigned int *suspend,
+                          unsigned int *off)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (reply)
+     {
+        if (standby) *standby = reply->standby_timeout;
+        if (suspend) *suspend = reply->suspend_timeout;
+        if (off) *off = 0;
+     }
+   else
+#endif /* ECORE_XCB_DPMS */
+     {
+        if (standby) *standby = 0;
+        if (suspend) *suspend = 0;
+        if (off) *off = 0;
+     }
+}
+
+
+/**
+ * Returns the amount of time of inactivity before standby mode is invoked.
+ * @return The standby timeout value.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_standby_get(void)
+{
+   int                            standby = 0;
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   standby = reply->standby_timeout;
+#endif /* ECORE_XCB_DPMS */
+
+   return standby;
+}
+
+
+/**
+ * Returns the amount of time of inactivity before the second level of
+ * power saving is invoked.
+ * @return The suspend timeout value.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_suspend_get(void)
+{
+   int                            suspend = 0;;
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   suspend = reply->suspend_timeout;
+#endif /* ECORE_XCB_DPMS */
+
+   return suspend;
+}
+
+
+/**
+ * Returns the amount of time of inactivity before the third and final
+ * level of power saving is invoked.
+ * @return The off timeout value.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_off_get(void)
+{
+   int                            off = 0;
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   off = reply->off_timeout;
+#endif /* ECORE_XCB_DPMS */
+
+   return off;
+}
+
+
+/**
+ * Sets the standby timeout (in unit of seconds).
+ * @param new_standby Amount of time of inactivity before standby mode will be invoked.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_standby_set(unsigned int new_standby)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_dpms_set_timeouts(_ecore_xcb_conn,
+                         new_standby,
+                         reply->suspend_timeout,
+                         reply->off_timeout);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Sets the suspend timeout (in unit of seconds).
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_suspend_set(unsigned int new_suspend)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_dpms_set_timeouts(_ecore_xcb_conn,
+                         reply->standby_timeout,
+                         new_suspend,
+                         reply->off_timeout);
+#endif /* ECORE_XCB_DPMS */
+}
+
+
+/**
+ * Sets the off timeout (in unit of seconds).
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request,
+ * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_off_set(unsigned int new_off)
+{
+#ifdef ECORE_XCB_DPMS
+   xcb_dpms_get_timeouts_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_dpms_set_timeouts(_ecore_xcb_conn,
+                         reply->standby_timeout,
+                         reply->suspend_timeout,
+                         new_off);
+#endif /* ECORE_XCB_DPMS */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_drawable.c b/src/lib/ecore_x/xcb/ecore_xcb_drawable.c
new file mode 100644 (file)
index 0000000..75b6911
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+#include <xcb/xcb.h>
+
+
+/**
+ * @defgroup Ecore_X_Drawable_Group X Drawable Functions
+ *
+ * Functions that operate on drawables.
+ */
+
+
+/**
+ * Sends the GetGeometry request.
+ * @param drawable Drawable whose characteristics are sought.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI void
+ecore_x_drawable_geometry_get_prefetch(Ecore_X_Drawable drawable)
+{
+   xcb_get_geometry_cookie_t cookie;
+
+   cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, drawable);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetGeometry request sent by ecore_x_atom_get_prefetch().
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI void
+ecore_x_drawable_geometry_get_fetch(void)
+{
+   xcb_get_geometry_cookie_t cookie;
+   xcb_get_geometry_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+
+/**
+ * Retrieves the geometry of the given drawable.
+ * @param drawable Unused.
+ * @param x        Pointer to an integer into which the X position is to be stored.
+ * @param y        Pointer to an integer into which the Y position is to be stored.
+ * @param width    Pointer to an integer into which the width is to be stored.
+ * @param height   Pointer to an integer into which the height is to be stored.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
+ * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI void
+ecore_x_drawable_geometry_get(Ecore_X_Drawable drawable __UNUSED__,
+                              int             *x,
+                              int             *y,
+                              int             *width,
+                              int             *height)
+{
+   xcb_get_geometry_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     {
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = 0;
+        if (height) *height = 0;
+        return;
+     }
+
+   if (x) *x = reply->x;
+   if (y) *y = reply->y;
+   if (width) *width = reply->width;
+   if (height) *height = reply->height;
+}
+
+
+/**
+ * Retrieves the width of the border of the given drawable.
+ * @param  drawable Unused.
+ * @return          The border width of the given drawable.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
+ * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI int
+ecore_x_drawable_border_width_get(Ecore_X_Drawable drawable __UNUSED__)
+{
+   xcb_get_geometry_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   return reply->border_width;
+}
+
+
+/**
+ * Retrieves the depth of the given drawable.
+ * @param  drawable Unused.
+ * @return          The depth of the given drawable.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
+ * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI int
+ecore_x_drawable_depth_get(Ecore_X_Drawable drawable __UNUSED__)
+{
+   xcb_get_geometry_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   return reply->depth;
+}
+
+/**
+ * Fill the specified rectangle on a drawable.
+ * @param d The given drawable.
+ * @param gc The graphic context that controls the fill rules.
+ * @param x The X coordinate of the top-left corner of the rectangle.
+ * @param y The Y coordinate of the top-left corner of the rectangle.
+ * @param width The width of the rectangle.
+ * @param height The height of the rectangle.
+ */
+EAPI void
+ecore_x_drawable_rectangle_fill(Ecore_X_Drawable d, Ecore_X_GC gc, int x, int y, int width, int height)
+{
+   xcb_rectangle_t rectangle;
+
+   rectangle.x = x;
+   rectangle.y = y;
+   rectangle.width = width;
+   rectangle.height = height;
+   xcb_poly_fill_rectangle(_ecore_xcb_conn, d, gc, 1, &rectangle);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_e.c b/src/lib/ecore_x/xcb/ecore_xcb_e.c
new file mode 100644 (file)
index 0000000..4c82617
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * OLD E hints
+ */
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+EAPI void
+ecore_x_e_frame_size_set(Ecore_X_Window window,
+                         int            fl,
+                         int            fr,
+                         int            ft,
+                         int            fb)
+{
+   uint32_t frames[4];
+
+   frames[0] = fl;
+   frames[1] = fr;
+   frames[2] = ft;
+   frames[3] = fb;
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_E_FRAME_SIZE, ECORE_X_ATOM_CARDINAL, 32,
+                       4, (const void *)frames);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_events.c b/src/lib/ecore_x/xcb/ecore_xcb_events.c
new file mode 100644 (file)
index 0000000..94d2c5c
--- /dev/null
@@ -0,0 +1,2168 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <Ecore.h>
+#include <Ecore_Input.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+/** OpenBSD does not define CODESET
+ * FIXME ??
+ */
+
+#ifndef CODESET
+#define CODESET "INVALID"
+#endif
+
+#if 0
+static void _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_title_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev);
+#endif
+
+static Ecore_X_Window _ecore_xcb_mouse_down_last_window = 0;
+static Ecore_X_Window _ecore_xcb_mouse_down_last_last_window = 0;
+static Ecore_X_Window _ecore_xcb_mouse_down_last_event_window = 0;
+static Ecore_X_Window _ecore_xcb_mouse_down_last_last_event_window = 0;
+static Ecore_X_Time   _ecore_xcb_mouse_down_last_time = 0;
+static Ecore_X_Time   _ecore_xcb_mouse_down_last_last_time = 0;
+static int            _ecore_xcb_mouse_up_count = 0;
+static int            _ecore_xcb_mouse_down_did_triple = 0;
+static int            _ecore_xcb_last_event_mouse_move = 0;
+static Ecore_Event   *_ecore_xcb_last_event_mouse_move_event = NULL;
+
+static void
+_ecore_x_event_free_mouse_move(void *data __UNUSED__, void *ev)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   e = ev;
+   if (_ecore_xcb_last_event_mouse_move)
+     {
+       _ecore_xcb_last_event_mouse_move_event = NULL;
+       _ecore_xcb_last_event_mouse_move = 0;
+     }
+   free(e);
+}
+
+
+/* FIXME: roundtrip */
+EAPI void
+ecore_x_event_mask_set(Ecore_X_Window     window,
+                       Ecore_X_Event_Mask mask)
+{
+   xcb_get_window_attributes_cookie_t cookie;
+   xcb_get_window_attributes_reply_t *reply;
+   uint32_t                           value_list;
+
+   if (!window)
+      window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
+   reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply) return;
+
+   value_list = mask | reply->your_event_mask;
+   xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list);
+   free(reply);
+}
+
+/* FIXME: roundtrip */
+EAPI void
+ecore_x_event_mask_unset(Ecore_X_Window     window,
+                         Ecore_X_Event_Mask mask)
+{
+   xcb_get_window_attributes_cookie_t cookie;
+   xcb_get_window_attributes_reply_t *reply;
+   uint32_t value_list;
+
+   if (!window)
+      window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
+   reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply) return;
+
+   value_list = reply->your_event_mask & ~mask;
+   xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list);
+   free(reply);
+}
+
+#if 0
+static void
+_ecore_x_event_free_window_prop_name_class_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Name_Class_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   if (e->clas) free(e->clas);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_title_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Title_Change *e;
+
+   e = ev;
+   if (e->title) free(e->title);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
+
+   e = ev;
+   if (e->title) free(e->title);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+#endif
+
+static void
+_ecore_x_event_free_xdnd_enter(void *data __UNUSED__, void *ev)
+{
+   Ecore_X_Event_Xdnd_Enter *e;
+   int                       i;
+
+   e = ev;
+   for (i = 0; i < e->num_types; i++)
+     free(e->types[i]);
+   free(e->types);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_selection_notify(void *data __UNUSED__, void *ev)
+{
+   Ecore_X_Event_Selection_Notify *e;
+   Ecore_X_Selection_Data         *sel;
+
+   e = ev;
+   sel = e->data;
+   if (sel->free)
+     sel->free(sel);
+   free(e->target);
+   free(e);
+}
+
+static unsigned int
+_ecore_x_event_modifiers(unsigned int state)
+{
+   unsigned int        modifiers = 0;
+
+   if (state & ECORE_X_MODIFIER_SHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+   if (state & ECORE_X_MODIFIER_CTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+   if (state & ECORE_X_MODIFIER_ALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
+   if (state & ECORE_X_MODIFIER_WIN) modifiers |= ECORE_EVENT_MODIFIER_WIN;
+   if (state & ECORE_X_LOCK_SCROLL) modifiers |= ECORE_EVENT_LOCK_SCROLL;
+   if (state & ECORE_X_LOCK_NUM) modifiers |= ECORE_EVENT_LOCK_NUM;
+   if (state & ECORE_X_LOCK_CAPS) modifiers |= ECORE_EVENT_LOCK_CAPS;
+
+   return modifiers;
+}
+
+static void
+_ecore_mouse_move(unsigned int timestamp, unsigned int xmodifiers,
+                 int x, int y,
+                 int x_root, int y_root,
+                 unsigned int event_window,
+                 unsigned int window,
+                 unsigned int root_win,
+                 int same_screen)
+{
+   Ecore_Event_Mouse_Move *e;
+   Ecore_Event            *event;
+
+   e = malloc(sizeof(Ecore_Event_Mouse_Move));
+   if (!e) return ;
+
+   e->window = window;
+   e->root_window = root_win;
+   e->timestamp = timestamp;
+   e->same_screen = same_screen;
+   e->event_window = event_window;
+
+   e->modifiers = _ecore_x_event_modifiers(xmodifiers);
+   e->x = x;
+   e->y = y;
+   e->root.x = x_root;
+   e->root.y = y_root;
+
+   event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _ecore_x_event_free_mouse_move, NULL);
+
+   _ecore_xcb_event_last_time = timestamp;
+   _ecore_xcb_event_last_window = window;
+   _ecore_xcb_event_last_root_x = x_root;
+   _ecore_xcb_event_last_root_y = y_root;
+
+   _ecore_xcb_last_event_mouse_move_event = event;
+}
+
+static void
+_ecore_key_press(int                  event,
+                xcb_generic_event_t *ev)
+{
+  /*
+   Ecore_Event_Key *e;
+   const char *compose = NULL;
+   char *tmp = NULL;
+   char *keyname;
+   char *key;
+   char keyname_buffer[256];
+   char compose_buffer[256];
+   KeySym sym;
+   XComposeStatus status;
+   int val;
+
+   _ecore_xcb_last_event_mouse_move = 0;
+   keyname = XKeysymToString(XKeycodeToKeysym(xevent->display,
+                                             xevent->keycode, 0));
+   if (!keyname)
+     {
+       snprintf(keyname_buffer, sizeof(keyname_buffer), "Keycode-%i", xevent->keycode);
+       keyname = keyname_buffer;
+       if (!keyname) return ;
+     }
+
+   sym = 0;
+   key = NULL;
+   compose = NULL;
+   if (_ecore_x_ic)
+     {
+       Status mbstatus;
+#ifdef X_HAVE_UTF8_STRING
+       val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
+#else
+       val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
+#endif
+       if (mbstatus == XBufferOverflow)
+         {
+            tmp = malloc(sizeof (char) * (val + 1));
+            if (!tmp) return ;
+
+            compose = tmp;
+
+#ifdef X_HAVE_UTF8_STRING
+            val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
+#else
+            val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
+#endif
+            if (val > 0)
+              {
+                 tmp[val] = 0;
+
+#ifndef X_HAVE_UTF8_STRING
+                 compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", tmp);
+                 free(tmp);
+                 tmp = compose;
+#endif
+              }
+            else compose = NULL;
+         }
+       else
+         if (val > 0)
+           {
+              compose_buffer[val] = 0;
+#ifdef X_HAVE_UTF8_STRING
+              compose = compose_buffer;
+#else
+              compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
+              tmp = compose;
+#endif
+           }
+     }
+   else
+     {
+       val = XLookupString(xevent, compose_buffer, sizeof(compose_buffer), &sym, &status);
+       if (val > 0)
+         {
+            compose_buffer[val] = 0;
+            compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
+            tmp = compose;
+         }
+     }
+
+   key = XKeysymToString(sym);
+   if (!key) key = keyname;
+   if (!key) goto on_error;
+
+   e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + (compose ? strlen(compose) : 0) + 3);
+   if (!e) goto on_error;
+
+   e->keyname = (char*) (e + 1);
+   e->key = e->keyname + strlen(keyname) + 1;
+   e->compose = (compose) ? e->key + strlen(key) + 1 : NULL;
+   e->string = e->compose;
+
+   strcpy((char *) e->keyname, keyname);
+   strcpy((char *) e->key, key);
+   if (compose) strcpy((char *) e->compose, compose);
+
+   e->modifiers = _ecore_x_event_modifiers(xevent->state);
+
+   e->timestamp = xevent->time;
+   e->window = xevent->subwindow ? xevent->subwindow : xevent->window;
+   e->event_window = xevent->window;
+   e->same_screen = xevent->same_screen;
+   e->root_window = xevent->root;
+
+   ecore_event_add(event, e, NULL, NULL);
+
+   _ecore_xcb_event_last_time = e->timestamp;
+
+ on_error:
+   if (tmp) free(tmp);
+  */
+}
+
+static Ecore_Event_Mouse_Button*
+_ecore_mouse_button(int event,
+                   unsigned int timestamp, unsigned int xmodifiers,
+                   unsigned int buttons,
+                   int x, int y,
+                   int x_root, int y_root,
+                   unsigned int event_window,
+                   unsigned int window,
+                   unsigned int root_win,
+                   int same_screen)
+{
+   Ecore_Event_Mouse_Button *e;
+
+   e = malloc(sizeof(Ecore_Event_Mouse_Button));
+   if (!e) return NULL;
+
+   e->window = window;
+   e->root_window = root_win;
+   e->timestamp = timestamp;
+   e->same_screen = same_screen;
+   e->event_window = event_window;
+
+   e->buttons = buttons;
+   e->modifiers = _ecore_x_event_modifiers(xmodifiers);
+   e->double_click = 0;
+   e->triple_click = 0;
+   e->x = x;
+   e->y = y;
+   e->root.x = x_root;
+   e->root.y = y_root;
+
+   if (event_window == window)
+     {
+       if (((int)(timestamp - _ecore_xcb_mouse_down_last_time) <=
+            (int)(1000 * _ecore_xcb_double_click_time)) &&
+           (window == _ecore_xcb_mouse_down_last_window) &&
+           (event_window == _ecore_xcb_mouse_down_last_event_window)
+           )
+         e->double_click = 1;
+       if (((int)(timestamp - _ecore_xcb_mouse_down_last_last_time) <=
+            (int)(2 * 1000 * _ecore_xcb_double_click_time)) &&
+           (window == _ecore_xcb_mouse_down_last_window) &&
+           (window == _ecore_xcb_mouse_down_last_last_window) &&
+           (event_window == _ecore_xcb_mouse_down_last_event_window) &&
+           (event_window == _ecore_xcb_mouse_down_last_last_event_window)
+           )
+         {
+            e->triple_click = 1;
+            _ecore_xcb_mouse_down_did_triple = 1;
+         }
+       else
+         _ecore_xcb_mouse_down_did_triple = 0;
+     }
+
+   if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN
+       && !e->double_click
+       && !e->triple_click)
+     _ecore_xcb_mouse_up_count = 0;
+
+   _ecore_xcb_event_last_time = e->timestamp;
+   _ecore_xcb_event_last_window = e->window;
+   _ecore_xcb_event_last_root_x = x_root;
+   _ecore_xcb_event_last_root_y = y_root;
+
+   ecore_event_add(event, e, NULL, NULL);
+
+   return e;
+}
+
+void
+_ecore_x_event_handle_any_event(xcb_generic_event_t *event)
+{
+   xcb_generic_event_t* ev = malloc(sizeof(xcb_generic_event_t));
+   memcpy(ev, event, sizeof(xcb_generic_event_t));
+
+   ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL);
+}
+
+/* FIXME: handle this event */
+void
+_ecore_x_event_handle_key_press(xcb_generic_event_t *event)
+{
+   _ecore_key_press(ECORE_EVENT_KEY_DOWN, event);
+
+   free(event);
+}
+
+/* FIXME: handle this event */
+void
+_ecore_x_event_handle_key_release(xcb_generic_event_t *event)
+{
+   _ecore_key_press(ECORE_EVENT_KEY_DOWN, event);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_button_press(xcb_generic_event_t *event)
+{
+   xcb_button_press_event_t *ev;
+   int                       i;
+
+   ev = (xcb_button_press_event_t *)event;
+   if ((ev->detail > 3) && (ev->detail < 8))
+     {
+       Ecore_Event_Mouse_Wheel *e;
+
+       e = malloc(sizeof(Ecore_Event_Mouse_Wheel));
+       if (!e) return;
+
+       e->timestamp = ev->time;
+       e->modifiers = _ecore_x_event_modifiers(ev->state);
+       switch (ev->detail)
+         {
+          case 4: e->direction = 0; e->z = -1; break;
+          case 5: e->direction = 0; e->z = 1; break;
+          case 6: e->direction = 1; e->z = -1; break;
+          case 7: e->direction = 1; e->z = 1; break;
+           default: e->direction = 0; e->z = 0; break;
+         }
+
+       e->x = ev->event_x;
+       e->y = ev->event_y;
+       e->root.x = ev->root_x;
+       e->root.y = ev->root_y;
+
+       if (ev->child)
+         e->window = ev->child;
+       else
+         e->window = ev->event;
+
+       e->event_window = ev->event;
+       e->same_screen = ev->same_screen;
+       e->root_window = ev->root;
+       _ecore_xcb_event_last_time = e->timestamp;
+       _ecore_xcb_event_last_window = e->window;
+       _ecore_xcb_event_last_root_x = e->root.x;
+       _ecore_xcb_event_last_root_y = e->root.y;
+       ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
+       for (i = 0; i < _ecore_window_grabs_num; i++)
+         {
+            if ((_ecore_window_grabs[i] == ev->event) ||
+                (_ecore_window_grabs[i] == ev->child))
+              {
+                 int replay = 0;
+
+                 if (_ecore_window_grab_replay_func)
+                   replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
+                                                           ECORE_EVENT_MOUSE_WHEEL,
+                                                           e);
+                  /* FIXME: xcb_key_press_event_t does not save the */
+                  /* connection. So I use the current one */
+                 if (replay)
+                   xcb_allow_events(_ecore_xcb_conn,
+                                     XCB_ALLOW_REPLAY_POINTER,
+                                     ev->time);
+                 else
+                   xcb_allow_events(_ecore_xcb_conn,
+                                     XCB_ALLOW_ASYNC_POINTER,
+                                     ev->time);
+                 break;
+              }
+         }
+     }
+   else
+     {
+        {
+          _ecore_mouse_move(ev->time, ev->state,
+                            ev->event_x, ev->event_y,
+                            ev->root_x, ev->root_y,
+                            ev->event,
+                            (ev->child ? ev->child : ev->event),
+                            ev->root,
+                            ev->same_screen);
+        }
+        {
+           Ecore_Event_Mouse_Button *e;
+           Ecore_X_Window            event_window;
+           Ecore_X_Window            child_window;
+
+           if (_ecore_xcb_mouse_down_did_triple)
+             {
+                _ecore_xcb_mouse_down_last_window = 0;
+                _ecore_xcb_mouse_down_last_last_window = 0;
+                _ecore_xcb_mouse_down_last_event_window = 0;
+                _ecore_xcb_mouse_down_last_last_event_window = 0;
+                _ecore_xcb_mouse_down_last_time = 0;
+                _ecore_xcb_mouse_down_last_last_time = 0;
+             }
+           event_window = ev->child;
+           child_window = ev->child ? ev->child : ev->event;
+
+          e = _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN,
+                                  ev->time, ev->state,
+                                  ev->detail,
+                                  ev->event_x, ev->event_y,
+                                  ev->root_x, ev->root_y,
+                                  event_window, child_window,
+                                  ev->root, ev->same_screen);
+
+           if (!e) return;
+           for (i = 0; i < _ecore_window_grabs_num; i++)
+             {
+                if ((_ecore_window_grabs[i] == ev->event) ||
+                    (_ecore_window_grabs[i] == ev->child))
+                  {
+                     int replay = 0;
+
+                     if (_ecore_window_grab_replay_func)
+                       replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
+                                                               ECORE_EVENT_MOUSE_BUTTON_DOWN,
+                                                               e);
+                     /* FIXME: xcb_key_press_event_t does not save the */
+                     /* connection. So I use the current one */
+                     if (replay)
+                       xcb_allow_events(_ecore_xcb_conn,
+                                        XCB_ALLOW_REPLAY_POINTER,
+                                        ev->time);
+                     else
+                       xcb_allow_events(_ecore_xcb_conn,
+                                        XCB_ALLOW_ASYNC_POINTER,
+                                        ev->time);
+                     break;
+                  }
+             }
+           if (child_window == event_window)
+             {
+                if (!_ecore_xcb_mouse_down_did_triple)
+                  {
+                     _ecore_xcb_mouse_down_last_last_window = _ecore_xcb_mouse_down_last_window;
+                     if (ev->child)
+                       _ecore_xcb_mouse_down_last_window = ev->child;
+                     else
+                       _ecore_xcb_mouse_down_last_window = ev->event;
+                     _ecore_xcb_mouse_down_last_last_event_window = _ecore_xcb_mouse_down_last_event_window;
+                     _ecore_xcb_mouse_down_last_event_window = ev->event;
+                     _ecore_xcb_mouse_down_last_last_time = _ecore_xcb_mouse_down_last_time;
+                     _ecore_xcb_mouse_down_last_time = ev->time;
+                  }
+             }
+        }
+     }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_button_release(xcb_generic_event_t *event)
+{
+   xcb_button_release_event_t *ev;
+
+   ev = (xcb_button_release_event_t *)event;
+   _ecore_xcb_last_event_mouse_move = 0;
+   /* filter out wheel buttons */
+   if ((ev->detail <= 3) || (ev->detail > 7))
+     {
+       _ecore_mouse_move(ev->time, ev->state,
+                         ev->event_x, ev->event_y,
+                         ev->root_x, ev->root_y,
+                         ev->event,
+                         (ev->child ? ev->child : ev->event),
+                         ev->root,
+                         ev->same_screen);
+
+       _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
+                           ev->time, ev->state,
+                           ev->detail,
+                           ev->event_x, ev->event_y,
+                           ev->root_x, ev->root_y,
+                           ev->event,
+                           (ev->child ? ev->child : ev->event),
+                           ev->root,
+                           ev->same_screen);
+     }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_motion_notify(xcb_generic_event_t *event)
+{
+   xcb_motion_notify_event_t *ev;
+
+   ev = (xcb_motion_notify_event_t *)event;
+   if (_ecore_xcb_last_event_mouse_move)
+     {
+        ecore_event_del(_ecore_xcb_last_event_mouse_move_event);
+        _ecore_xcb_last_event_mouse_move = 0;
+        _ecore_xcb_last_event_mouse_move_event = NULL;
+     }
+
+   _ecore_mouse_move(ev->time, ev->state,
+                    ev->event_x, ev->event_y,
+                    ev->root_x, ev->root_y,
+                    ev->event,
+                    (ev->child ? ev->child : ev->event),
+                    ev->root,
+                    ev->same_screen);
+
+   _ecore_xcb_last_event_mouse_move = 1;
+
+   /* Xdnd handling */
+   _ecore_x_dnd_drag(ev->root, ev->root_x, ev->root_y);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_enter_notify(xcb_generic_event_t *event)
+{
+   xcb_enter_notify_event_t *ev;
+
+   ev = (xcb_enter_notify_event_t *)event;
+   _ecore_xcb_last_event_mouse_move = 0;
+
+   {
+      _ecore_mouse_move(ev->time, ev->state,
+                        ev->event_x, ev->event_y,
+                        ev->root_x, ev->root_y,
+                        ev->event,
+                        (ev->child ? ev->child : ev->event),
+                        ev->root,
+                        ev->same_screen_focus);
+   }
+   {
+      Ecore_X_Event_Mouse_In *e;
+
+      e = calloc(1, sizeof(Ecore_X_Event_Mouse_In));
+      if (!e) return;
+      e->modifiers = _ecore_x_event_modifiers(ev->state);
+      e->x = ev->event_x;
+      e->y = ev->event_y;
+      e->root.x = ev->root_x;
+      e->root.y = ev->root_y;
+      if (ev->child) e->win = ev->child;
+      else e->win = ev->event;
+      e->same_screen = ev->same_screen_focus;
+      e->root_win = ev->root;
+      e->event_win = ev->event;
+      switch (ev->mode) {
+      case XCB_NOTIFY_MODE_NORMAL:
+        e->mode = ECORE_X_EVENT_MODE_NORMAL;
+        break;
+      case XCB_NOTIFY_MODE_GRAB:
+        e->mode = ECORE_X_EVENT_MODE_GRAB;
+        break;
+      case XCB_NOTIFY_MODE_UNGRAB:
+        e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+        break;
+      default:
+        e->mode = ECORE_X_EVENT_MODE_NORMAL;
+        break;
+      }
+      switch (ev->detail) {
+      case XCB_NOTIFY_DETAIL_ANCESTOR:
+        e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+        break;
+      case XCB_NOTIFY_DETAIL_VIRTUAL:
+        e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+        break;
+      case XCB_NOTIFY_DETAIL_INFERIOR:
+        e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+        break;
+      case XCB_NOTIFY_DETAIL_NONLINEAR:
+        e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+        break;
+      case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
+        e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+        break;
+      default:
+        e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+        break;
+      }
+      e->time = ev->time;
+      _ecore_xcb_event_last_time = e->time;
+      ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL);
+   }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_leave_notify(xcb_generic_event_t *event)
+{
+   xcb_leave_notify_event_t *ev;
+
+   ev = (xcb_leave_notify_event_t *)event;
+   _ecore_xcb_last_event_mouse_move = 0;
+
+   {
+      _ecore_mouse_move(ev->time, ev->state,
+                        ev->event_x, ev->event_y,
+                        ev->root_x, ev->root_y,
+                        ev->event,
+                        (ev->child ? ev->child : ev->event),
+                        ev->root,
+                        ev->same_screen_focus);
+   }
+   {
+      Ecore_X_Event_Mouse_Out *e;
+
+      e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out));
+      if (!e) return;
+      e->modifiers = _ecore_x_event_modifiers(ev->state);
+      e->x = ev->event_x;
+      e->y = ev->event_y;
+      e->root.x = ev->root_x;
+      e->root.y = ev->root_y;
+      if (ev->child) e->win = ev->child;
+      else e->win = ev->event;
+      e->same_screen = ev->same_screen_focus;
+      e->root_win = ev->root;
+      e->event_win = ev->event;
+      switch (ev->mode) {
+      case XCB_NOTIFY_MODE_NORMAL:
+        e->mode = ECORE_X_EVENT_MODE_NORMAL;
+        break;
+      case XCB_NOTIFY_MODE_GRAB:
+        e->mode = ECORE_X_EVENT_MODE_GRAB;
+        break;
+      case XCB_NOTIFY_MODE_UNGRAB:
+        e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+        break;
+      default:
+        e->mode = ECORE_X_EVENT_MODE_NORMAL;
+        break;
+      }
+      switch (ev->detail) {
+      case XCB_NOTIFY_DETAIL_ANCESTOR:
+        e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+        break;
+      case XCB_NOTIFY_DETAIL_VIRTUAL:
+        e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+        break;
+      case XCB_NOTIFY_DETAIL_INFERIOR:
+        e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+        break;
+      case XCB_NOTIFY_DETAIL_NONLINEAR:
+        e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+        break;
+      case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
+        e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+        break;
+      default:
+        e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+        break;
+      }
+      e->time = ev->time;
+      _ecore_xcb_event_last_time = e->time;
+      _ecore_xcb_event_last_window = e->win;
+      _ecore_xcb_event_last_root_x = e->root.x;
+      _ecore_xcb_event_last_root_y = e->root.y;
+      ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL);
+   }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_focus_in(xcb_generic_event_t *event)
+{
+   xcb_focus_in_event_t          *ev;
+   Ecore_X_Event_Window_Focus_In *e;
+
+   ev = (xcb_focus_in_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In));
+   if (!e) return;
+   e->win = ev->event;
+   switch (ev->mode) {
+   case XCB_NOTIFY_MODE_NORMAL:
+     e->mode = ECORE_X_EVENT_MODE_NORMAL;
+     break;
+   case XCB_NOTIFY_MODE_GRAB:
+     e->mode = ECORE_X_EVENT_MODE_GRAB;
+     break;
+   case XCB_NOTIFY_MODE_UNGRAB:
+     e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+     break;
+   case XCB_NOTIFY_MODE_WHILE_GRABBED:
+     e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
+     break;
+   }
+   switch (ev->detail) {
+   case XCB_NOTIFY_DETAIL_ANCESTOR:
+     e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+     break;
+   case XCB_NOTIFY_DETAIL_VIRTUAL:
+     e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+     break;
+   case XCB_NOTIFY_DETAIL_INFERIOR:
+     e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+     break;
+   case XCB_NOTIFY_DETAIL_NONLINEAR:
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+     break;
+   case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+     break;
+   case XCB_NOTIFY_DETAIL_POINTER:
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER;
+     break;
+   case XCB_NOTIFY_DETAIL_POINTER_ROOT:
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
+     break;
+   case XCB_NOTIFY_DETAIL_NONE:
+     e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
+     break;
+   }
+   e->time = _ecore_xcb_event_last_time;
+   _ecore_xcb_event_last_time = e->time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_focus_out(xcb_generic_event_t *event)
+{
+   xcb_focus_out_event_t            *ev;
+   Ecore_X_Event_Window_Focus_Out *e;
+
+   ev = (xcb_focus_out_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out));
+   if (!e) return;
+   e->win = ev->event;
+   switch (ev->mode) {
+   case XCB_NOTIFY_MODE_NORMAL:
+     e->mode = ECORE_X_EVENT_MODE_NORMAL;
+     break;
+   case XCB_NOTIFY_MODE_GRAB:
+     e->mode = ECORE_X_EVENT_MODE_GRAB;
+     break;
+   case XCB_NOTIFY_MODE_UNGRAB:
+     e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+     break;
+   case XCB_NOTIFY_MODE_WHILE_GRABBED:
+     e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
+     break;
+   }
+   switch (ev->detail) {
+   case XCB_NOTIFY_DETAIL_ANCESTOR:
+     e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+     break;
+   case XCB_NOTIFY_DETAIL_VIRTUAL:
+     e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+     break;
+   case XCB_NOTIFY_DETAIL_INFERIOR:
+     e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+     break;
+   case XCB_NOTIFY_DETAIL_NONLINEAR:
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+     break;
+   case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+     break;
+   case XCB_NOTIFY_DETAIL_POINTER:
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER;
+     break;
+   case XCB_NOTIFY_DETAIL_POINTER_ROOT:
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
+     break;
+   case XCB_NOTIFY_DETAIL_NONE:
+     e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
+     break;
+   }
+   e->time = _ecore_xcb_event_last_time;
+   _ecore_xcb_event_last_time = e->time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_keymap_notify(xcb_generic_event_t *event)
+{
+   /* FIXME: handle this event type */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_expose(xcb_generic_event_t *event)
+{
+   xcb_expose_event_t            *ev;
+   Ecore_X_Event_Window_Damage *e;
+
+   ev = (xcb_expose_event_t *)event,
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
+   if (!e) return;
+   e->win = ev->window;
+   e->time = _ecore_xcb_event_last_time;
+   e->x = ev->x;
+   e->y = ev->y;
+   e->w = ev->width;
+   e->h = ev->height;
+   e->count = ev->count;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_graphics_expose(xcb_generic_event_t *event)
+{
+   xcb_graphics_exposure_event_t *ev;
+   Ecore_X_Event_Window_Damage *e;
+
+   ev = (xcb_graphics_exposure_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
+   if (!e) return;
+   e->win = ev->drawable;
+   e->time = _ecore_xcb_event_last_time;
+   e->x = ev->x;
+   e->y = ev->y;
+   e->w = ev->width;
+   e->h = ev->height;
+   e->count = ev->count;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_visibility_notify(xcb_generic_event_t *event)
+{
+   xcb_visibility_notify_event_t *ev;
+
+   ev = (xcb_visibility_notify_event_t *)event;
+   if (ev->state != XCB_VISIBILITY_PARTIALLY_OBSCURED)
+   {
+      Ecore_X_Event_Window_Visibility_Change *e;
+
+      e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change));
+      if (!e) return;
+      e->win = ev->window;
+      e->time = _ecore_xcb_event_last_time;
+      if (ev->state == XCB_VISIBILITY_FULLY_OBSCURED)
+        e->fully_obscured = 1;
+      else
+        e->fully_obscured = 0;
+      ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL);
+   }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_create_notify(xcb_generic_event_t *event)
+{
+   xcb_create_notify_event_t     *ev;
+   Ecore_X_Event_Window_Create *e;
+
+   ev = (xcb_create_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Create));
+   if (!e) return;
+   e->win = ev->window;
+   if (ev->override_redirect)
+      e->override = 1;
+   else
+      e->override = 0;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_destroy_notify(xcb_generic_event_t *event)
+{
+   xcb_destroy_notify_event_t     *ev;
+   Ecore_X_Event_Window_Destroy *e;
+
+   ev = (xcb_destroy_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy));
+   if (!e) return;
+   e->win =  ev->window;
+   e->time = _ecore_xcb_event_last_time;
+   if (e->win == _ecore_xcb_event_last_window) _ecore_xcb_event_last_window = 0;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_unmap_notify(xcb_generic_event_t *event)
+{
+   xcb_unmap_notify_event_t    *ev;
+   Ecore_X_Event_Window_Hide *e;
+
+   ev = (xcb_unmap_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Hide));
+   if (!e) return;
+   e->win = ev->window;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_map_notify(xcb_generic_event_t *event)
+{
+   xcb_map_notify_event_t      *ev;
+   Ecore_X_Event_Window_Show *e;
+
+   ev = (xcb_map_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Show));
+   if (!e) return;
+   e->win = ev->window;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_map_request(xcb_generic_event_t *event)
+{
+   xcb_map_request_event_t             *ev;
+   Ecore_X_Event_Window_Show_Request *e;
+
+   ev = (xcb_map_request_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request));
+   if (!e) return;
+   e->win = ev->window;
+   e->parent = ev->parent;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_reparent_notify(xcb_generic_event_t *event)
+{
+   xcb_reparent_notify_event_t     *ev;
+   Ecore_X_Event_Window_Reparent *e;
+
+   ev = (xcb_reparent_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent));
+   if (!e) return;
+   e->win = ev->window;
+   e->parent = ev->parent;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_configure_notify(xcb_generic_event_t *event)
+{
+   xcb_configure_notify_event_t     *ev;
+   Ecore_X_Event_Window_Configure *e;
+
+   ev = (xcb_configure_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Configure));
+   if (!e) return;
+   e->win = ev->window;
+   e->abovewin = ev->above_sibling;
+   e->x = ev->x;
+   e->y = ev->y;
+   e->w = ev->width;
+   e->h = ev->height;
+   e->border = ev->border_width;
+   e->override = ev->override_redirect;
+   /* send_event is bit 7 (0x80) of response_type */
+   e->from_wm = (ev->response_type & 0x80) ? 1 : 0;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_configure_request(xcb_generic_event_t *event)
+{
+   xcb_configure_request_event_t            *ev;
+   Ecore_X_Event_Window_Configure_Request *e;
+
+   ev = (xcb_configure_request_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request));
+   if (!e) return;
+   e->win = ev->window;
+   e->abovewin = ev->sibling;
+   e->x = ev->x;
+   e->y = ev->y;
+   e->w = ev->width;
+   e->h = ev->height;
+   e->border = ev->border_width;
+   e->value_mask = ev->value_mask;
+   switch (ev->stack_mode) {
+   case XCB_STACK_MODE_ABOVE:
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+     break;
+   case XCB_STACK_MODE_BELOW:
+     e->detail = ECORE_X_WINDOW_STACK_BELOW;
+     break;
+   case XCB_STACK_MODE_TOP_IF:
+     e->detail = ECORE_X_WINDOW_STACK_TOP_IF;
+     break;
+   case XCB_STACK_MODE_BOTTOM_IF:
+     e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF;
+     break;
+   case XCB_STACK_MODE_OPPOSITE:
+     e->detail = ECORE_X_WINDOW_STACK_OPPOSITE;
+     break;
+   }
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_gravity_notify(xcb_generic_event_t *event)
+{
+   /* FIXME: handle this event type */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_resize_request(xcb_generic_event_t *event)
+{
+   xcb_resize_request_event_t            *ev;
+   Ecore_X_Event_Window_Resize_Request *e;
+
+   ev = (xcb_resize_request_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request));
+   if (!e) return;
+   e->win = ev->window;
+   e->w = ev->width;
+   e->h = ev->height;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_circulate_notify(xcb_generic_event_t *event)
+{
+   xcb_circulate_notify_event_t *ev;
+   Ecore_X_Event_Window_Stack *e;
+
+   ev = (xcb_circulate_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Stack));
+   if (!e) return;
+   e->win = ev->window;
+   e->event_win = ev->event;
+   if (ev->place == XCB_PLACE_ON_TOP)
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+   else
+     e->detail = ECORE_X_WINDOW_STACK_BELOW;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_circulate_request(xcb_generic_event_t *event)
+{
+   xcb_circulate_request_event_t        *ev;
+   Ecore_X_Event_Window_Stack_Request *e;
+
+   ev = (xcb_circulate_request_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request));
+   if (!e) return;
+   e->win = ev->window;
+   e->parent = ev->event;
+   if (ev->place == XCB_PLACE_ON_TOP)
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+   else
+     e->detail = ECORE_X_WINDOW_STACK_BELOW;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_property_notify(xcb_generic_event_t *event)
+{
+#if 0 /* for now i disabled this. nice idea though this is - it leaves a lot
+       * to be desired for efficiency that is better left to the app layer
+       */
+   if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLASS)
+     {
+       Ecore_X_Event_Window_Prop_Name_Class_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Name_Class_Change));
+       if (!e) return;
+       ecore_x_window_prop_name_class_get(xevent->xproperty.window,
+                                          &(e->name), &(e->clas));
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, e, _ecore_x_event_free_window_prop_name_class_change, NULL);
+     }
+   else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_NAME))
+     {
+       Ecore_X_Event_Window_Prop_Title_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Title_Change));
+       if (!e) return;
+       e->title = ecore_x_window_prop_title_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_title_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_NAME)
+     {
+       Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Title_Change));
+       if (!e) return;
+       e->title = ecore_x_window_prop_visible_title_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_visible_title_change, NULL);
+     }
+   else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_ICON_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_ICON_NAME))
+     {
+       Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Icon_Name_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_icon_name_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_icon_name_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME)
+     {
+       Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_visible_icon_name_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_visible_icon_name_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
+     {
+       Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Client_Machine_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_client_machine_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, e, _ecore_x_event_free_window_prop_client_machine_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_PID)
+     {
+       Ecore_X_Event_Window_Prop_Pid_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Pid_Change));
+       if (!e) return;
+       e->pid = ecore_x_window_prop_pid_get(xevent->xproperty.window);
+   e->time = xevent->xproperty.time;
+   _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_DESKTOP)
+     {
+       Ecore_X_Event_Window_Prop_Desktop_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Desktop_Change));
+       if (!e) return;
+       e->desktop = ecore_x_window_prop_desktop_get(xevent->xproperty.window);
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
+     }
+   else
+#endif
+   {
+      xcb_property_notify_event_t     *ev;
+      Ecore_X_Event_Window_Property *e;
+
+      ev = (xcb_property_notify_event_t *)event;
+      e = calloc(1,sizeof(Ecore_X_Event_Window_Property));
+      if (!e) return;
+      e->win = ev->window;
+      e->atom = ev->atom;
+      e->time = ev->time;
+      _ecore_xcb_event_last_time = e->time;
+      ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL);
+   }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_selection_clear(xcb_generic_event_t *event)
+{
+   xcb_selection_clear_event_t     *ev;
+   Ecore_X_Selection_Intern      *d;
+   Ecore_X_Event_Selection_Clear *e;
+   Ecore_X_Atom                   sel;
+
+   ev = (xcb_selection_clear_event_t *)event;
+   d = _ecore_x_selection_get(ev->selection);
+   if (d && (ev->time > d->time))
+     {
+       _ecore_x_selection_set(XCB_NONE, NULL, 0,
+                               ev->selection);
+     }
+
+   /* Generate event for app cleanup */
+   e = malloc(sizeof(Ecore_X_Event_Selection_Clear));
+   e->win = ev->owner;
+   e->time = ev->time;
+   e->atom = sel = ev->selection;
+   if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
+     e->selection = ECORE_X_SELECTION_PRIMARY;
+   else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
+     e->selection = ECORE_X_SELECTION_SECONDARY;
+   else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     e->selection = ECORE_X_SELECTION_CLIPBOARD;
+   else
+     e->selection = ECORE_X_SELECTION_OTHER;
+   ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_selection_request(xcb_generic_event_t *event)
+{
+   xcb_selection_request_event_t *ev;
+   Ecore_X_Selection_Intern    *sd;
+   xcb_selection_notify_event_t   sn_event;
+   void                          *data;
+
+   ev = (xcb_selection_request_event_t *)event;
+   /* FIXME: is it the correct value ? */
+   sn_event.response_type = XCB_SELECTION_NOTIFY;
+   sn_event.pad0 = 0;
+   /* FIXME: is it the correct value ? */
+   sn_event.sequence = 0;
+   sn_event.time = XCB_CURRENT_TIME;
+   sn_event.requestor = ev->requestor;
+   sn_event.selection = ev->selection;
+   sn_event.target = ev->target;
+
+   if ((sd = _ecore_x_selection_get(ev->selection)) &&
+       (sd->win == ev->owner))
+     {
+       if (!ecore_x_selection_convert(ev->selection, ev->target,
+                                       &data))
+         {
+            /* Refuse selection, conversion to requested target failed */
+            sn_event.property = XCB_NONE;
+         }
+       else
+         {
+            /* FIXME: This does not properly handle large data transfers */
+            ecore_x_window_prop_property_set(ev->requestor,
+                                              ev->property,
+                                              ev->target,
+                                              8, data, sd->length);
+            sn_event.property = ev->property;
+            free(data);
+         }
+     }
+   else
+     {
+       sn_event.property = XCB_NONE;
+       return;
+     }
+
+   /* FIXME: I use _ecore_xcb_conn, as ev has no information on the connection */
+   xcb_send_event(_ecore_xcb_conn, 0,
+                  ev->requestor, 0, (const char *)&sn_event);
+
+   free(event);
+}
+
+/* FIXME: round trip */
+void
+_ecore_x_event_handle_selection_notify(xcb_generic_event_t *event)
+{
+   xcb_selection_notify_event_t   *ev;
+   Ecore_X_Event_Selection_Notify *e;
+   unsigned char                 *data = NULL;
+   Ecore_X_Atom                   selection;
+   int                            num_ret;
+   uint8_t                        format;
+
+   ev = (xcb_selection_notify_event_t *)event;
+   selection = ev->selection;
+
+   if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS)
+     {
+        ecore_x_window_prop_property_get_prefetch(ev->requestor,
+                                                  ev->property,
+                                                  ECORE_X_ATOM_ATOM);
+        ecore_x_window_prop_property_get_fetch();
+        format = ecore_x_window_prop_property_get(ev->requestor,
+                                                  ev->property,
+                                                  ECORE_X_ATOM_ATOM,
+                                                  32,
+                                                  &data,
+                                                  &num_ret);
+       if (!format) return;
+     }
+   else
+     {
+        ecore_x_window_prop_property_get_prefetch(ev->requestor,
+                                                  ev->property,
+                                                  XCB_GET_PROPERTY_TYPE_ANY);
+        ecore_x_window_prop_property_get_fetch();
+        format = ecore_x_window_prop_property_get(ev->requestor,
+                                                  ev->property,
+                                                  ECORE_X_ATOM_ATOM,
+                                                  8,
+                                                  &data,
+                                                  &num_ret);
+       if (!format) return;
+     }
+
+   e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify));
+   if (!e) return;
+   e->win = ev->requestor;
+   e->time = ev->time;
+   e->atom = selection;
+   e->target = _ecore_x_selection_target_get(ev->target);
+
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     e->selection = ECORE_X_SELECTION_PRIMARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     e->selection = ECORE_X_SELECTION_SECONDARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     e->selection = ECORE_X_SELECTION_XDND;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     e->selection = ECORE_X_SELECTION_CLIPBOARD;
+   else
+     e->selection = ECORE_X_SELECTION_OTHER;
+
+   e->data = _ecore_x_selection_parse(e->target, data, num_ret, format);
+
+   ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_colormap_notify(xcb_generic_event_t *event)
+{
+   xcb_colormap_notify_event_t     *ev;
+   Ecore_X_Event_Window_Colormap *e;
+
+   ev = (xcb_colormap_notify_event_t *)event;
+   e = calloc(1,sizeof(Ecore_X_Event_Window_Colormap));
+   if (!e) return;
+   e->win = ev->window;
+   e->cmap = ev->colormap;
+   if (ev->state == XCB_COLORMAP_STATE_INSTALLED)
+      e->installed = 1;
+   else
+      e->installed = 0;
+   e->time = _ecore_xcb_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL);
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_client_message(xcb_generic_event_t *event)
+{
+   /* Special client message event handling here. need to put LOTS of if */
+   /* checks here and generate synthetic events per special message known */
+   /* otherwise generate generic client message event. this would handle*/
+   /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */
+
+   xcb_client_message_event_t *ev;
+
+   ev = (xcb_client_message_event_t *)event;
+   if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) &&
+       (ev->format == 32) &&
+       (ev->data.data32[0] == (uint32_t)ECORE_X_ATOM_WM_DELETE_WINDOW))
+     {
+       Ecore_X_Event_Window_Delete_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request));
+       if (!e) return;
+       e->win = ev->window;
+       e->time = _ecore_xcb_event_last_time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
+     }
+
+   else if ((ev->type == ECORE_X_ATOM_NET_WM_MOVERESIZE) &&
+           (ev->format == 32) &&
+           /* Ignore move and resize with keyboard */
+           (ev->data.data32[2] < 9))
+     {
+       Ecore_X_Event_Window_Move_Resize_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request));
+       if (!e) return;
+       e->win = ev->window;
+       e->x = ev->data.data32[0];
+       e->y = ev->data.data32[1];
+       e->direction = ev->data.data32[2];
+       e->button = ev->data.data32[3];
+       e->source = ev->data.data32[4];
+       ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL);
+     }
+
+   /* Xdnd Client Message Handling Begin */
+   /* Message Type: XdndEnter target */
+   else if (ev->type == ECORE_X_ATOM_XDND_ENTER)
+     {
+       Ecore_X_Event_Xdnd_Enter *e;
+       Ecore_X_DND_Target       *target;
+       uint32_t                  three;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter));
+       if (!e) return;
+
+       target = _ecore_x_dnd_target_get();
+       target->state = ECORE_X_DND_TARGET_ENTERED;
+
+       target = _ecore_x_dnd_target_get();
+       target->source = ev->data.data32[0];
+       target->win = ev->window;
+       target->version = ev->data.data32[1] >> 24;
+       if (target->version > ECORE_X_DND_VERSION)
+         {
+             WRN("DND: Requested version %d, we only support up to %d", target->version,
+                    ECORE_X_DND_VERSION);
+            return;
+         }
+
+        /* FIXME: roud trip, but I don't know how to suppress it */
+       if ((three = ev->data.data32[1] & 0x1UL))
+         {
+            /* source supports more than 3 types, fetch property */
+            unsigned char *data;
+            Ecore_X_Atom  *types;
+            int            num_ret;
+            int            i;
+             uint8_t        format;
+
+             ecore_x_window_prop_property_get_prefetch(target->source,
+                                                       ECORE_X_ATOM_XDND_TYPE_LIST,
+                                                       ECORE_X_ATOM_ATOM);
+             ecore_x_window_prop_property_get_fetch();
+             format = ecore_x_window_prop_property_get(target->source,
+                                                       ECORE_X_ATOM_XDND_TYPE_LIST,
+                                                       ECORE_X_ATOM_ATOM,
+                                                       32,
+                                                       &data,
+                                                       &num_ret);
+             if (!format)
+              {
+                 ERR("DND: Could not fetch data type list from source window, aborting.");
+                 return;
+              }
+            types = (Ecore_X_Atom *)data;
+            e->types = calloc(num_ret, sizeof(char *));
+            if (e->types)
+              {
+                  xcb_get_atom_name_cookie_t *cookies;
+
+                  cookies = (xcb_get_atom_name_cookie_t *)malloc(sizeof(xcb_get_atom_name_cookie_t) * num_ret);
+                  for (i = 0; i < num_ret; i++)
+                    cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, types[i]);
+                 for (i = 0; i < num_ret; i++)
+                    {
+                       xcb_get_atom_name_reply_t *reply;
+                       char                      *name;
+
+                       reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL);
+                       if (reply)
+                         {
+                            name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
+                            memcpy(name,
+                                   xcb_get_atom_name_name(reply),
+                                   reply->name_len);
+                            name[reply->name_len] = '\0';
+                            e->types[i] = name;
+                            free(reply);
+                         }
+                    }
+                  free(cookies);
+              }
+            e->num_types = num_ret;
+         }
+       else
+         {
+            int i = 0;
+
+            e->types = calloc(3, sizeof(char *));
+            if (e->types)
+              {
+                  xcb_get_atom_name_cookie_t cookies[3];
+
+                  for (i = 0; i < 3; i++)
+                    cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[i + 2]);
+                  for (i = 0; i < 3; i++)
+                    {
+                       xcb_get_atom_name_reply_t *reply;
+                       char                      *name;
+
+                       reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL);
+                       if (reply && (ev->data.data32[i + 2]))
+                         {
+                            name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
+                            memcpy(name,
+                                   xcb_get_atom_name_name(reply),
+                                   reply->name_len);
+                            name[reply->name_len] = '\0';
+                            e->types[i] = name;
+                         }
+                       if (reply) free(reply);
+                    }
+              }
+            e->num_types = i;
+         }
+
+       e->win = target->win;
+       e->source = target->source;
+       ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, _ecore_x_event_free_xdnd_enter, NULL);
+     }
+
+   /* Message Type: XdndPosition target */
+   else if (ev->type == ECORE_X_ATOM_XDND_POSITION)
+     {
+       Ecore_X_Event_Xdnd_Position *e;
+       Ecore_X_DND_Target          *target;
+
+       target = _ecore_x_dnd_target_get();
+       if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
+           (target->win != ev->window))
+         return;
+
+       target->pos.x = (int16_t)ev->data.data32[2] >> 16;
+       target->pos.y = (int16_t)ev->data.data32[2] & 0xFFFFUL;
+       target->action = ev->data.data32[4]; /* Version 2 */
+
+       target->time = (target->version >= 1) ?
+          ev->data.data32[3] : XCB_CURRENT_TIME;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position));
+       if (!e) return;
+       e->win = target->win;
+       e->source = target->source;
+       e->position.x = target->pos.x;
+       e->position.y = target->pos.y;
+       e->action = target->action;
+       ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndStatus source */
+   else if (ev->type == ECORE_X_ATOM_XDND_STATUS)
+     {
+       Ecore_X_Event_Xdnd_Status *e;
+       Ecore_X_DND_Source        *source;
+
+       source = _ecore_x_dnd_source_get();
+       /* Make sure source/target match */
+       if ((source->win != ev->window ) ||
+           (source->dest != ev->data.data32[0]))
+         return;
+
+       source->await_status = 0;
+
+       source->will_accept = ev->data.data32[1] & 0x1UL;
+       source->suppress = (ev->data.data32[1] & 0x2UL) ? 0 : 1;
+
+       source->rectangle.x = (int16_t)ev->data.data32[2] >> 16;
+       source->rectangle.y = (int16_t)ev->data.data32[2] & 0xFFFFUL;
+       source->rectangle.width = (uint16_t)ev->data.data32[3] >> 16;
+       source->rectangle.height = (uint16_t)ev->data.data32[3] & 0xFFFFUL;
+
+       source->accepted_action = ev->data.data32[4];
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status));
+       if (!e) return;
+       e->win = source->win;
+       e->target = source->dest;
+       e->will_accept = source->will_accept;
+       e->rectangle.x = source->rectangle.x;
+       e->rectangle.y = source->rectangle.y;
+       e->rectangle.width = source->rectangle.width;
+       e->rectangle.height = source->rectangle.height;
+       e->action = source->accepted_action;
+
+       ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndLeave target */
+   /* Pretend the whole thing never happened, sort of */
+   else if (ev->type == ECORE_X_ATOM_XDND_LEAVE)
+     {
+       Ecore_X_Event_Xdnd_Leave *e;
+       Ecore_X_DND_Target       *target;
+
+       target = _ecore_x_dnd_target_get();
+       if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
+           (target->win != ev->window))
+         return;
+
+       target->state = ECORE_X_DND_TARGET_IDLE;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave));
+       if (!e) return;
+       e->win = ev->window;
+       e->source = ev->data.data32[0];
+       ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndDrop target */
+   else if (ev->type == ECORE_X_ATOM_XDND_DROP)
+     {
+       Ecore_X_Event_Xdnd_Drop *e;
+       Ecore_X_DND_Target      *target;
+
+       target = _ecore_x_dnd_target_get();
+       /* Match source/target */
+       if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
+           (target->win != ev->window))
+         return;
+
+       target->time = (target->version >= 1) ?
+          ev->data.data32[2] : _ecore_xcb_event_last_time;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop));
+       if (!e) return;
+       e->win = target->win;
+       e->source = target->source;
+       e->action = target->action;
+       e->position.x = target->pos.x;
+       e->position.y = target->pos.y;
+       ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndFinished source */
+   else if (ev->type == ECORE_X_ATOM_XDND_FINISHED)
+     {
+       Ecore_X_Event_Xdnd_Finished *e;
+       Ecore_X_DND_Source          *source;
+       uint8_t                        completed = 1;
+
+       source = _ecore_x_dnd_source_get();
+       /* Match source/target */
+       if ((source->win != ev->window) ||
+           (source->dest != ev->data.data32[0]))
+         return;
+
+       if ((source->version >= 5) && (ev->data.data32[1] & 0x1UL))
+         {
+            /* Target successfully performed drop action */
+            ecore_x_selection_xdnd_clear();
+            source->state = ECORE_X_DND_SOURCE_IDLE;
+         }
+       else
+         {
+              completed = 0;
+              source->state = ECORE_X_DND_SOURCE_CONVERTING;
+
+              /* FIXME: Probably need to add a timer to switch back to idle
+               * and discard the selection data */
+         }
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished));
+       if (!e) return;
+       e->win = source->win;
+       e->target = source->dest;
+       e->completed = completed;
+       if (source->version >= 5)
+         {
+            source->accepted_action = ev->data.data32[2];
+            e->action = source->accepted_action;
+         }
+       else
+         {
+            source->accepted_action = 0;
+            e->action = source->action;
+         }
+
+       ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL);
+     }
+   else if (ev->type == ECORE_X_ATOM_NET_WM_STATE)
+     {
+       Ecore_X_Event_Window_State_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
+       if (!e) return;
+       e->win = ev->window;
+       if (ev->data.data32[0] == 0)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE;
+       else if (ev->data.data32[0] == 1)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
+       else if (ev->data.data32[0] == 2)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE;
+       else
+         {
+            free(e);
+            return;
+         }
+       e->state[0] = _ecore_x_netwm_state_get(ev->data.data32[1]);
+       if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN)
+         {
+             xcb_get_atom_name_reply_t *reply;
+            char                      *name;
+
+             /* FIXME: round trip */
+             reply = xcb_get_atom_name_reply(_ecore_xcb_conn,
+                                             xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[1]),
+                                             NULL);
+            if (reply)
+               {
+                 name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
+                 memcpy(name,
+                        xcb_get_atom_name_name(reply),
+                        reply->name_len);
+                 name[reply->name_len] = '\0';
+                 ERR("Unknown state: %s", name);
+                 free(name);
+                 free(reply);
+               }
+         }
+       e->state[1] = _ecore_x_netwm_state_get(ev->data.data32[2]);
+       if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN)
+         {
+             xcb_get_atom_name_reply_t *reply;
+            char                      *name;
+
+             reply = xcb_get_atom_name_reply(_ecore_xcb_conn,
+                                             xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[2]),
+                                             NULL);
+            if (reply)
+               {
+                 name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
+                 memcpy(name,
+                        xcb_get_atom_name_name(reply),
+                        reply->name_len);
+                 name[reply->name_len] = '\0';
+                 WRN("Unknown state: %s", name);
+                 free(name);
+               }
+         }
+       e->source = ev->data.data32[3];
+
+       ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
+     }
+   else if ((ev->type == ECORE_X_ATOM_WM_CHANGE_STATE)
+           && (ev->format == 32)
+           && (ev->data.data32[0] == XCB_WM_HINT_STATE))
+     {
+       Ecore_X_Event_Window_State_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
+       if (!e) return;
+       e->win = ev->window;
+       e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
+       e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED;
+
+       ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
+     }
+   else if ((ev->type == ECORE_X_ATOM_NET_WM_DESKTOP)
+           && (ev->format == 32))
+     {
+       Ecore_X_Event_Desktop_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change));
+       if (!e) return;
+       e->win = ev->window;
+       e->desk = ev->data.data32[0];
+       e->source = ev->data.data32[1];
+
+       ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL);
+     }
+   else if ((ev->type == ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS))
+     {
+       Ecore_X_Event_Frame_Extents_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request));
+       if (!e) return;
+       e->win = ev->window;
+
+       ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL);
+     }
+   else if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS)
+           && ((Ecore_X_Atom)ev->data.data32[0] == ECORE_X_ATOM_NET_WM_PING)
+           && (ev->format == 32))
+     {
+       Ecore_X_Event_Ping *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Ping));
+       if (!e) return;
+       e->win = ev->window;
+       e->time = ev->data.data32[1];
+       e->event_win = ev->data.data32[2];
+
+       ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL);
+     }
+   else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) &&
+           (ev->format == 8))
+     {
+       _ecore_x_netwm_startup_info_begin(ev->window, (char *)ev->data.data8);
+     }
+   else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO) &&
+           (ev->format == 8))
+     {
+       _ecore_x_netwm_startup_info(ev->window, (char *)ev->data.data8);
+     }
+   else if ((ev->type == 27777)
+           && (ev->data.data32[0] == 0x7162534)
+           && (ev->format == 32)
+           && (ev->window == _ecore_xcb_private_window))
+     {
+       /* a grab sync marker */
+       if (ev->data.data32[1] == 0x10000001)
+         _ecore_x_window_grab_remove(ev->data.data32[2]);
+       else if (ev->data.data32[1] == 0x10000002)
+         _ecore_x_key_grab_remove(ev->data.data32[2]);
+     }
+   else
+     {
+       Ecore_X_Event_Client_Message *e;
+       int i;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Client_Message));
+       if (!e) return;
+       e->win = ev->window;
+       e->message_type = ev->type;
+       e->format = ev->format;
+       for (i = 0; i < 5; i++)
+         e->data.l[i] = ev->data.data32[i];
+
+       ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL);
+     }
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_mapping_notify(xcb_generic_event_t *event)
+{
+   /* FIXME: handle this event type */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_shape_change(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_SHAPE
+   xcb_shape_notify_event_t     *ev;
+   Ecore_X_Event_Window_Shape *e;
+
+   ev = (xcb_shape_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Shape));
+   if (!e) return;
+   e->win = ev->affected_window;
+   e->time = ev->server_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL);
+#endif /* ECORE_X_SHAPE */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_screensaver_notify(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_SCREENSAVER
+   xcb_screensaver_notify_event_t     *ev;
+   Ecore_X_Event_Screensaver_Notify *e;
+
+   ev = (xcb_screensaver_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify));
+   if (!e) return;
+   e->win = ev->window;
+   if (ev->state == XCB_SCREENSAVER_STATE_ON)
+     e->on = 1;
+   else
+     e->on = 0;
+   e->time = ev->time;
+   ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL);
+#endif /* ECORE_X_SCREENSAVER */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_sync_counter(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_SYNC
+   xcb_sync_counter_notify_event_t *ev;
+   Ecore_X_Event_Sync_Counter    *e;
+
+   ev = (xcb_sync_counter_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter));
+   if (!e) return;
+   e->time = ev->timestamp;
+   ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL);
+#endif /* ECORE_X_SYNC */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_sync_alarm(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_SYNC
+   xcb_sync_alarm_notify_event_t *ev;
+   Ecore_X_Event_Sync_Alarm    *e;
+
+   ev = (xcb_sync_alarm_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm));
+   if (!e) return;
+   e->time = ev->timestamp;
+   e->alarm = ev->alarm;
+   ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL);
+#endif /* ECORE_X_SYNC */
+
+   free(event);
+}
+
+/* FIXME: round trip */
+void
+_ecore_x_event_handle_randr_change(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_RANDR
+   xcb_randr_screen_change_notify_event_t *ev;
+   Ecore_X_Event_Screen_Change            *e;
+
+   ev = (xcb_randr_screen_change_notify_event_t *)event;
+
+   if ((ev->response_type & ~0x80) != XCB_CONFIGURE_NOTIFY)
+     {
+       xcb_query_extension_reply_t *rep;
+
+       rep = xcb_query_extension_reply(_ecore_xcb_conn,
+                                       xcb_query_extension_unchecked(_ecore_xcb_conn,
+                                                                     strlen("randr"),
+                                                                     "randr"),
+                                       NULL);
+
+     if ((!rep) ||
+         (((ev->response_type & ~0x80) - rep->first_event) != XCB_RANDR_SCREEN_CHANGE_NOTIFY))
+       WRN("ERROR: Can't update RandR config!");
+     if (rep)
+       free(rep);
+     }
+
+   e = calloc(1, sizeof(Ecore_X_Event_Screen_Change));
+   if (!e) return;
+   e->win = ev->request_window;
+   e->root = ev->root;
+   e->width = ev->width;
+   e->height = ev->height;
+   ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL);
+#endif /* ECORE_X_RANDR */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_fixes_selection_notify(xcb_generic_event_t *event)
+{
+#ifdef ECORE_X_FIXES
+   /* Nothing here yet */
+#endif /* ECORE_X_FIXES */
+
+   free(event);
+}
+
+void
+_ecore_x_event_handle_damage_notify(xcb_generic_event_t *event)
+{
+#ifdef ECORE_XCBDAMAGE
+   xcb_damage_notify_event_t *ev;
+   Ecore_X_Event_Damage      *e;
+
+   ev = (xcb_damage_notify_event_t *)event;
+   e = calloc(1, sizeof(Ecore_X_Event_Damage));
+   if (!e) return;
+
+   e->level = ev->level;
+   e->drawable = ev->drawable;
+   e->damage = ev->damage;
+   /* FIXME: XCB has no 'more' member in xcb_damage_notify_event_t */
+/*    e->more = ev->more; */
+   e->time = ev->timestamp;
+   e->area.x = ev->area.x;
+   e->area.y = ev->area.y;
+   e->area.width = ev->area.width;
+   e->area.height = ev->area.height;
+   e->geometry.x = ev->geometry.x;
+   e->geometry.y = ev->geometry.y;
+   e->geometry.width = ev->geometry.width;
+   e->geometry.height = ev->geometry.height;
+
+   ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL);
+#endif /* ECORE_XCBDAMAGE */
+
+   free(event);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_fixes.c b/src/lib/ecore_x/xcb/ecore_xcb_fixes.c
new file mode 100644 (file)
index 0000000..d4014d4
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Fixes_Group X Fixes Extension Functions
+ *
+ * Functions related to the X Fixes extension.
+ */
+
+
+#ifdef ECORE_XCB_FIXES
+static int _xfixes_available = 0;
+static xcb_xfixes_query_version_cookie_t _ecore_xcb_xfixes_init_cookie;
+#endif /* ECORE_XCB_FIXES */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_xfixes_init and
+   _ecore_xcb_xfixes_init_finalize. The first one gets the cookies and
+   the second one gets the replies and set the atoms. */
+
+void
+_ecore_x_xfixes_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_FIXES
+   if (reply && (reply->present))
+      _ecore_xcb_xfixes_init_cookie = xcb_xfixes_query_version_unchecked(_ecore_xcb_conn, 4, 0);
+#endif /* ECORE_XCB_FIXES */
+}
+
+void
+_ecore_x_xfixes_init_finalize(void)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_query_version_reply_t *reply;
+
+   reply = xcb_xfixes_query_version_reply(_ecore_xcb_conn,
+                                          _ecore_xcb_xfixes_init_cookie, NULL);
+
+   if (reply)
+     {
+        if (reply->major_version >= 3)
+          _xfixes_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Return whether the X server supports the Fixes Extension.
+ * @return 1 if the X Fixes Extension is available, 0 otherwise.
+ *
+ * Return 1 if the X server supports the Fixes Extension version 3.0,
+ * 0 otherwise.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI int
+ecore_x_xfixes_query(void)
+{
+#ifdef ECORE_XCB_FIXES
+   return _xfixes_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Create a region from rectangles.
+ * @param rects The rectangles used to initialize the region.
+ * @param num   The number of rectangles.
+ * @return      The newly created region.
+ *
+ * Create a region initialized to the specified list of rectangles
+ * @p rects. The rectangles may be specified in any order, their union
+ * becomes the region.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Region
+ecore_x_region_new(Ecore_X_Rectangle *rects,
+                   int                num)
+{
+   Ecore_X_Region region = XCB_NONE;
+
+#ifdef ECORE_XCB_FIXES
+   region = xcb_generate_id(_ecore_xcb_conn);
+   xcb_xfixes_create_region(_ecore_xcb_conn, region, num, (xcb_rectangle_t *)rects);
+#endif /* ECORE_XCB_FIXES */
+
+   return region;
+}
+
+
+/**
+ * Create a region from a pixmap.
+ * @param bitmap The bitmap used to initialize the region.
+ * @return       The newly created region.
+ *
+ * Creates a region initialized to the set of 'one' pixels in @p bitmap
+ * (which must be of depth 1, else Match error).
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Region
+ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap)
+{
+   Ecore_X_Region region = XCB_NONE;
+
+#ifdef ECORE_XCB_FIXES
+   region = xcb_generate_id(_ecore_xcb_conn);
+   xcb_xfixes_create_region_from_bitmap(_ecore_xcb_conn, region, bitmap);
+#endif /* ECORE_XCB_FIXES */
+
+   return region;
+}
+
+
+/**
+ * Create a region from a window.
+ * @param window The window used to initialize the region.
+ * @param type   The type of the region.
+ * @return       The newly created region.
+ *
+ * Creates a region initialized to the specified @p window region. See
+ * the Shape extension for the definition of Bounding and Clip
+ * regions.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Region
+ecore_x_region_new_from_window(Ecore_X_Window      window,
+                               Ecore_X_Region_Type type)
+{
+   Ecore_X_Region region = XCB_NONE;
+
+#ifdef ECORE_XCB_FIXES
+   region = xcb_generate_id(_ecore_xcb_conn);
+   xcb_xfixes_create_region_from_window(_ecore_xcb_conn, region, window, type);
+#endif /* ECORE_XCB_FIXES */
+
+   return region;
+}
+
+
+/**
+ * Create a region from a graphic context.
+ * @param gc The graphic context used to initialize the region.
+ * @return   The newly created region.
+ *
+ * Creates a region initialized from the clip list of @p gc.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Region
+ecore_x_region_new_from_gc(Ecore_X_GC gc)
+{
+   Ecore_X_Region region = XCB_NONE;
+
+#ifdef ECORE_XCB_FIXES
+   region = xcb_generate_id(_ecore_xcb_conn);
+   xcb_xfixes_create_region_from_gc(_ecore_xcb_conn, region, gc);
+#endif /* ECORE_XCB_FIXES */
+
+   return region;
+}
+
+
+/**
+ * Create a region from a picture.
+ * @param picture The picture used to initialize the region.
+ * @return        The newly created region.
+ *
+ * Creates a region initialized from the clip list of @p picture.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Region
+ecore_x_region_new_from_picture(Ecore_X_Picture picture)
+{
+   Ecore_X_Region region = XCB_NONE;
+
+#ifdef ECORE_XCB_FIXES
+   region = xcb_generate_id(_ecore_xcb_conn);
+   xcb_xfixes_create_region_from_picture(_ecore_xcb_conn, region, picture);
+#endif /* ECORE_XCB_FIXES */
+
+   return region;
+}
+
+
+/**
+ * Destroy a region.
+ * @param region The region to destroy.
+ *
+ * Destroy the specified @p region.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_free(Ecore_X_Region region)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_destroy_region(_ecore_xcb_conn, region);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Set the content of a region.
+ * @param region The region to destroy.
+ * @param rects  The rectangles used to set the region.
+ * @param num    The number of rectangles.
+ *
+ * Replace the current contents of @p region with the region formed
+ * by the union of the rectangles @p rects.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_set(Ecore_X_Region     region,
+                   Ecore_X_Rectangle *rects,
+                   int                num)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_set_region(_ecore_xcb_conn, region, num, (xcb_rectangle_t *)rects);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Copy the content of a region.
+ * @param dest   The destination region.
+ * @param source The source region.
+ *
+ * Replace the contents of @p dest with the contents of @p source.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_copy(Ecore_X_Region dest,
+                    Ecore_X_Region source)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_copy_region(_ecore_xcb_conn, source, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Make the union of two regions.
+ * @param dest    The destination region.
+ * @param source1 The first source region.
+ * @param source2 The second source region.
+ *
+ * Replace the contents of @p dest with the union of @p source1 and
+ * @p source2.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_combine(Ecore_X_Region dest,
+                       Ecore_X_Region source1,
+                       Ecore_X_Region source2)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_union_region(_ecore_xcb_conn, source1, source2, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Make the intersection of two regions.
+ * @param dest    The destination region.
+ * @param source1 The first source region.
+ * @param source2 The second source region.
+ *
+ * Replace the contents of @p dest with the intersection of @p source1 and
+ * @p source2.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_intersect(Ecore_X_Region dest,
+                         Ecore_X_Region source1,
+                         Ecore_X_Region source2)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_intersect_region(_ecore_xcb_conn, source1, source2, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Make the substraction of two regions.
+ * @param dest    The destination region.
+ * @param source1 The first source region.
+ * @param source2 The second source region.
+ *
+ * Replace the contents of @p dest with the substraction of @p source1 by
+ * @p source2.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_subtract(Ecore_X_Region dest,
+                        Ecore_X_Region source1,
+                        Ecore_X_Region source2)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_subtract_region(_ecore_xcb_conn, source1, source2, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Make the substraction of regions by bounds.
+ * @param dest   The destination region.
+ * @param bounds The bounds.
+ * @param source The source region.
+ *
+ * The @p source region is subtracted from the region specified by
+ * @p bounds.  The result is placed in @p dest, replacing its
+ * contents.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_invert(Ecore_X_Region     dest,
+                      Ecore_X_Rectangle *bounds,
+                      Ecore_X_Region     source)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_rectangle_t rect;
+
+   rect.x = bounds->x;
+   rect.y = bounds->y;
+   rect.width = bounds->width;
+   rect.height = bounds->height;
+   xcb_xfixes_invert_region(_ecore_xcb_conn, source, rect, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Translate a region.
+ * @param region The region to translate.
+ * @param dx     The horizontal translation.
+ * @param dy     The vertical translation.
+ *
+ * The @p region is translated by @p dx and @p dy in place.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_translate(Ecore_X_Region region,
+                         int            dx,
+                         int            dy)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_translate_region(_ecore_xcb_conn, region, dx, dy);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Extent a region.
+ * @param dest   The destination region.
+ * @param source The source region.
+ *
+ * The extents of the @p source region are placed in @p dest.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_extents(Ecore_X_Region dest,
+                       Ecore_X_Region source)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_region_extents(_ecore_xcb_conn, source, dest);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Sends the XFixesFetchRegion request.
+ * @param region Requested region.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_fetch_prefetch(Ecore_X_Region region)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_fetch_region_cookie_t cookie;
+
+   cookie = xcb_xfixes_fetch_region_unchecked(_ecore_xcb_conn, region);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Gets the reply of the XFixesFetchRegion request sent by ecore_xcb_region_fetch_prefetch().
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_fetch_fetch(void)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_fetch_region_cookie_t cookie;
+   xcb_xfixes_fetch_region_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_xfixes_fetch_region_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Return the rectangles that compose a region.
+ * @param  region The region (Unused).
+ * @param  num    The number of returned rectangles.
+ * @param  bounds The returned bounds of the region.
+ * @return        The returned rectangles.
+ *
+ * The @p region passed to ecore_xcb_region_fetch_prefetch() is
+ * returned as a list of rectagles in XY-banded order.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_xcb_region_fetch_prefetch(), which sends the XFixesFetchRegion request,
+ * then ecore_xcb_region_fetch_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI Ecore_X_Rectangle *
+ecore_x_region_fetch(Ecore_X_Region     region __UNUSED__,
+                     int               *num,
+                     Ecore_X_Rectangle *bounds)
+{
+   Ecore_X_Rectangle  extents = { 0, 0, 0, 0};
+   Ecore_X_Rectangle *rects = NULL;
+#ifdef ECORE_XCB_FIXES
+   int                n;
+   xcb_xfixes_fetch_region_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     {
+       if (num) *num = 0;
+       if (bounds) *bounds = extents;
+       return NULL;
+     }
+   n = xcb_xfixes_fetch_region_rectangles_length(reply);
+   rects = (Ecore_X_Rectangle *)malloc(n * sizeof(Ecore_X_Rectangle));
+   if (!rects)
+     {
+       if (num) *num = 0;
+       if (bounds) *bounds = extents;
+
+       return NULL;
+     }
+
+   if (num) *num = n;
+   if (bounds)
+     {
+        bounds->x = reply->extents.x;
+        bounds->y = reply->extents.y;
+        bounds->width = reply->extents.width;
+        bounds->height = reply->extents.height;
+     }
+   memcpy(rects,
+          xcb_xfixes_fetch_region_rectangles(reply),
+          sizeof(Ecore_X_Rectangle) * n);
+
+   return rects;
+#else
+   if (num) *num = 0;
+   if (bounds) *bounds = extents;
+   return NULL;
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Expand a region.
+ * @param dest   The destination region.
+ * @param source The source region.
+ * @param left   The number of pixels to add on the left.
+ * @param right  The number of pixels to add on the right.
+ * @param top    The number of pixels to add at the top.
+ * @param bottom The number of pixels to add at the bottom.
+ *
+ * Put in @p dest the area specified by expanding each rectangle in
+ * the @p source  region by the specified number of pixels to the
+ * @p left, @p right, @p top and @p bottom.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_expand(Ecore_X_Region dest,
+                      Ecore_X_Region source,
+                      unsigned int   left,
+                      unsigned int   right,
+                      unsigned int   top,
+                      unsigned int   bottom)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_expand_region(_ecore_xcb_conn, source, dest, left, right, top, bottom);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Change clip-mask in a graphic context to the specified region.
+ * @param region   The region to change.
+ * @param gc       The clip-mask graphic context.
+ * @param x_origin The horizontal translation.
+ * @param y_origin The vertical translation.
+ *
+ * Changes clip-mask in @p gc to the specified @p region and
+ * sets the clip origin with the values of @p x_origin and @p y_origin.
+ * Output will be clippped to remain contained within the region. The
+ * clip origin is interpreted relative to the origin of whatever
+ * destination drawable is specified in a graphics request. The
+ * region is interpreted relative to the clip origin. Future changes
+ * to region have no effect on the gc clip-mask.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_gc_clip_set(Ecore_X_Region region,
+                           Ecore_X_GC     gc,
+                           int            x_origin,
+                           int            y_origin)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_set_gc_clip_region(_ecore_xcb_conn, gc, region, x_origin, y_origin);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Change the shape extension of a window.
+ * @param region   The region.
+ * @param dest     The window whose shape is changed.
+ * @param type     The kind of shape.
+ * @param x_offset The horizontal offset.
+ * @param y_offset The vertical offset.
+ *
+ * Set the specified Shape extension region of @p window to @p region,
+ * offset by @p x_offset and @p y_offset. Future changes to region
+ * have no effect on the window shape.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_window_shape_set(Ecore_X_Region     region,
+                                Ecore_X_Window     dest,
+                                Ecore_X_Shape_Type type,
+                                int                x_offset,
+                                int                y_offset)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_set_window_shape_region(_ecore_xcb_conn, dest, type, x_offset, y_offset, region);
+#endif /* ECORE_XCB_FIXES */
+}
+
+
+/**
+ * Change clip-mask in picture to the specified region.
+ * @param region   The region.
+ * @param picture  The picture.
+ * @param x_origin The X coordinate of the origin.
+ * @param y_origin The Y coordinate of the origin.
+ *
+ * Changes clip-mask in picture to the specified @p region
+ * and sets the clip origin.  Input and output will be clipped to
+ * remain contained within the region.  The clip origin is interpreted
+ * relative to the origin of the drawable associated with @p picture.  The
+ * region is interpreted relative to the clip origin.  Future changes
+ * to region have no effect on the picture clip-mask.
+ * @ingroup Ecore_X_Fixes_Group
+ */
+EAPI void
+ecore_x_region_picture_clip_set(Ecore_X_Region  region,
+                                Ecore_X_Picture picture,
+                                int             x_origin,
+                                int             y_origin)
+{
+#ifdef ECORE_XCB_FIXES
+   xcb_xfixes_set_picture_clip_region(_ecore_xcb_conn, picture, region, x_origin, y_origin);
+#endif /* ECORE_XCB_FIXES */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_gc.c b/src/lib/ecore_x/xcb/ecore_xcb_gc.c
new file mode 100644 (file)
index 0000000..83d019b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * Creates a new default graphics context associated with the given
+ * drawable.
+ * @param  drawable Drawable to create graphics context with.  If @c 0 is
+ *                  given instead, the default root window is used.
+ * @param value_mask Bitmask values.
+ * @param value_list List of values. The order of values must be the
+ *                   same than the corresponding bitmaks.
+ * @return          The new default graphics context.
+ *
+ * Creates a new default graphics context associated with @p
+ * drawable. The graphic context can be used with any destination
+ * drawable having the same root and depth as @p drawable. Use with
+ * other drawables results in a BadMatch error.
+ */
+EAPI Ecore_X_GC
+ecore_x_gc_new(Ecore_X_Drawable drawable, Ecore_X_GC_Value_Mask value_mask, const unsigned int *value_list)
+{
+   xcb_gcontext_t gc;
+
+   if (!drawable) drawable = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   gc = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_gc(_ecore_xcb_conn, gc, drawable, value_mask, value_list);
+
+   return gc;
+}
+
+
+/**
+ * Deletes and frees the given graphics context.
+ * @param gc The given graphics context.
+ *
+ * Destroyes the graphic context @p gc as well as the associated
+ * storage.
+ */
+EAPI void
+ecore_x_gc_free(Ecore_X_GC gc)
+{
+   xcb_free_gc(_ecore_xcb_conn, gc);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_icccm.c b/src/lib/ecore_x/xcb/ecore_xcb_icccm.c
new file mode 100644 (file)
index 0000000..b356cf2
--- /dev/null
@@ -0,0 +1,1898 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * Various ICCCM related functions.
+ *
+ * This is ALL the code involving anything ICCCM related, for both WM and
+ * client.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xcb/xcb_icccm.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+/**
+ * @defgroup Ecore_X_ICCCM_Group ICCCM related functions.
+ *
+ * Functions related to ICCCM.
+ */
+
+
+static int _ecore_x_icccm_size_hints_get (const void       *reply,
+                                          Ecore_X_Atom      property,
+                                          xcb_size_hints_t *hints)
+{
+   uint32_t s;
+
+   if (!hints) return 0;
+
+   if (!reply) return 0;
+   if ((((xcb_get_property_reply_t *)reply)->type != ECORE_X_ATOM_WM_SIZE_HINTS) &&
+       ((((xcb_get_property_reply_t *)reply)->format != 8)  ||
+        (((xcb_get_property_reply_t *)reply)->format != 16) ||
+        (((xcb_get_property_reply_t *)reply)->format != 32))                &&
+       (((xcb_get_property_reply_t *)reply)->value_len < 15)) /* OldNumPropSizeElements = 15 (pre-ICCCM) */
+      return 0;
+
+   memcpy(hints,
+          xcb_get_property_value((xcb_get_property_reply_t *)reply),
+          ((xcb_get_property_reply_t *)reply)->value_len);
+
+   s = (XCB_SIZE_HINT_US_POSITION  | XCB_SIZE_HINT_US_SIZE   |
+        XCB_SIZE_HINT_P_POSITION   | XCB_SIZE_HINT_P_SIZE    |
+        XCB_SIZE_HINT_P_MIN_SIZE   | XCB_SIZE_HINT_P_MAX_SIZE |
+        XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_P_ASPECT);
+
+   if (((xcb_get_property_reply_t *)reply)->value_len >= 18) /* NumPropSizeElements = 18 (ICCCM version 1) */
+      s |= (XCB_SIZE_HINT_BASE_SIZE | XCB_SIZE_HINT_P_WIN_GRAVITY);
+   else
+     {
+        xcb_size_hints_set_base_size(hints, 0, 0);
+        xcb_size_hints_set_win_gravity(hints, 0);
+     }
+   /* FIXME: is it necessary ? */
+   /* hints->flags &= s; */         /* get rid of unwanted bits */
+
+   return 1;
+}
+
+
+/**
+ * Sets the state of a window.
+ * @param window The window.
+ * @param state  The state.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_state_set(Ecore_X_Window            window,
+                        Ecore_X_Window_State_Hint state)
+{
+   uint32_t c[2];
+
+   if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
+      c[0] = XCB_WM_STATE_WITHDRAWN;
+   else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
+      c[0] = XCB_WM_STATE_NORMAL;
+   else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
+      c[0] = XCB_WM_STATE_ICONIC;
+   c[1] = 0;
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_STATE, ECORE_X_ATOM_WM_STATE, 32,
+                       2, c);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_state_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_STATE,
+                                       ECORE_X_ATOM_WM_STATE,
+                                       0L, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_state_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_state_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Gets the state of a window.
+ * @param window The window.
+ * @return       The state of the window
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_state_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_state_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI Ecore_X_Window_State_Hint
+ecore_x_icccm_state_get(Ecore_X_Window window __UNUSED__)
+{
+   xcb_get_property_reply_t   *reply;
+   uint8_t                    *prop;
+   Ecore_X_Window_State_Hint hint = ECORE_X_WINDOW_STATE_HINT_NONE;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return hint;
+
+   if ((reply->type == 0) ||
+       (reply->format != 8) ||
+       (reply->value_len != 2))
+      return hint;
+
+   prop = (uint8_t *)xcb_get_property_value(reply);
+   switch (prop[0]) {
+   case XCB_WM_STATE_WITHDRAWN:
+     hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
+     break;
+   case XCB_WM_STATE_NORMAL:
+     hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+     break;
+   case XCB_WM_STATE_ICONIC:
+     hint = ECORE_X_WINDOW_STATE_HINT_ICONIC;
+     break;
+   default:
+     hint = ECORE_X_WINDOW_STATE_HINT_NONE;
+     break;
+   }
+
+   return hint;
+}
+
+/**
+ * Sends the ClientMessage event with the DeleteWindow property.
+ * @param window The window.
+ * @param time   The time.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_delete_window_send(Ecore_X_Window window,
+                                 Ecore_X_Time   time)
+{
+   ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS,
+                                 ECORE_X_EVENT_MASK_NONE,
+                                 ECORE_X_ATOM_WM_DELETE_WINDOW,
+                                 time, 0, 0, 0);
+}
+
+/**
+ * Sends the ClientMessage event with the TakeFocus property.
+ * @param window The window.
+ * @param time   The time.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_take_focus_send(Ecore_X_Window window,
+                              Ecore_X_Time   time)
+{
+   ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS,
+                                 ECORE_X_EVENT_MASK_NONE,
+                                 ECORE_X_ATOM_WM_TAKE_FOCUS,
+                                 time, 0, 0, 0);
+}
+
+/**
+ * Sends the ClientMessage event with the SaveYourself property.
+ * @param window The window.
+ * @param time   The time.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_save_yourself_send(Ecore_X_Window window,
+                                 Ecore_X_Time   time)
+{
+   ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS,
+                                 ECORE_X_EVENT_MASK_NONE,
+                                 ECORE_X_ATOM_WM_SAVE_YOURSELF,
+                                 time, 0, 0, 0);
+}
+
+/**
+ * Sends the ConfigureNotify event with the StructureNotify property.
+ * @param window The window.
+ * @param x      The X coordinate.
+ * @param y      The Y coordinate.
+ * @param width  The width.
+ * @param height The height.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_move_resize_send(Ecore_X_Window window,
+                               int            x,
+                               int            y,
+                               int            width,
+                               int            height)
+{
+   xcb_configure_notify_event_t ev;
+
+   ev.response_type = XCB_CONFIGURE_NOTIFY | 0x80;
+   ev.pad0 = 0;
+   ev.sequence = 0;
+   ev.event = window;
+   ev.window = window;
+   ev.above_sibling = 0;
+   ev.x = x;
+   ev.y = y;
+   ev.width = width;
+   ev.height = height;
+   ev.border_width = 0;
+   ev.override_redirect = 0;
+   xcb_send_event(_ecore_xcb_conn, 0, window,
+                  XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *)&ev);
+}
+
+/**
+ * Sets the hints of a window.
+ * @param window        The window.
+ * @param accepts_focus AcceptFocus hint
+ * @param initial_state Initial state flags.
+ * @param icon_pixmap   Icon pixmap.
+ * @param icon_mask     Icon mask.
+ * @param icon_window   Icon window.
+ * @param window_group  Group window.
+ * @param is_urgent     IsUrgent flag.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_hints_set(Ecore_X_Window            window,
+                       int                       accepts_focus,
+                       Ecore_X_Window_State_Hint initial_state,
+                       Ecore_X_Pixmap            icon_pixmap,
+                       Ecore_X_Pixmap            icon_mask,
+                       Ecore_X_Window            icon_window,
+                       Ecore_X_Window            window_group,
+                        int                       is_urgent)
+{
+   xcb_wm_hints_t hints;
+
+   memset(&hints, 0, sizeof(hints));
+   xcb_wm_hints_set_input(&hints, accepts_focus);
+   if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
+      xcb_wm_hints_set_withdrawn(&hints);
+   else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
+      xcb_wm_hints_set_normal(&hints);
+   else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
+      xcb_wm_hints_set_iconic(&hints);
+   if (icon_pixmap != 0)
+     xcb_wm_hints_set_icon_pixmap(&hints, icon_pixmap);
+   if (icon_mask != 0)
+     xcb_wm_hints_set_icon_mask(&hints, icon_mask);
+   if (icon_window != 0)
+     xcb_wm_hints_set_icon_window(&hints, icon_window);
+   if (window_group != 0)
+     xcb_wm_hints_set_window_group(&hints, window_group);
+   if (is_urgent)
+     xcb_wm_hints_set_urgency(&hints);
+   xcb_set_wm_hints(_ecore_xcb_conn, window, &hints);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_hints_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_HINTS,
+                                       ECORE_X_ATOM_WM_HINTS,
+                                       0L, XCB_NUM_WM_HINTS_ELEMENTS);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_hints_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_hints_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Gets the hints of a window.
+ * @param window        The window.
+ * @param accepts_focus AcceptFocus hint
+ * @param initial_state Initial state flags.
+ * @param icon_pixmap   Icon pixmap.
+ * @param icon_mask     Icon mask.
+ * @param icon_window   Icon window.
+ * @param window_group  Group window.
+ * @param is_urgent     IsUrgent flag.
+ * @return              1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_hints_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_hints_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI int
+ecore_x_icccm_hints_get(Ecore_X_Window             window __UNUSED__,
+                       int                       *accepts_focus,
+                       Ecore_X_Window_State_Hint *initial_state,
+                       Ecore_X_Pixmap            *icon_pixmap,
+                       Ecore_X_Pixmap            *icon_mask,
+                       Ecore_X_Window            *icon_window,
+                       Ecore_X_Window            *window_group,
+                        int                       *is_urgent)
+{
+   xcb_wm_hints_t            hints;
+   xcb_get_property_reply_t *reply;
+   uint32_t                  flags;
+
+   if (accepts_focus)
+      *accepts_focus = 1;
+   if (initial_state)
+      *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+   if (icon_pixmap)
+      *icon_pixmap = 0;
+   if (icon_mask)
+      *icon_mask = 0;
+   if (icon_window)
+      *icon_window = 0;
+   if (window_group)
+      *window_group = 0;
+   if (is_urgent)
+      *is_urgent = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return 0;
+
+   if ((reply->type != ECORE_X_ATOM_WM_HINTS) ||
+       (reply->value_len < (XCB_NUM_WM_HINTS_ELEMENTS - 1)) ||
+       (reply->format != 32))
+      return 0;
+
+   xcb_get_wm_hints_from_reply(&hints, reply);
+
+   flags = xcb_wm_hints_get_flags(&hints);
+   if ((flags & XCB_WM_HINT_INPUT) && (accepts_focus))
+     {
+        if (xcb_wm_hints_get_input(hints))
+           *accepts_focus = 1;
+        else
+           *accepts_focus = 0;
+     }
+   if ((flags & XCB_WM_HINT_STATE) && (initial_state))
+     {
+       if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_STATE_WITHDRAWN)
+           *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
+        else if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_STATE_NORMAL)
+           *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+        else if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_STATE_ICONIC)
+           *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
+     }
+   if ((flags & XCB_WM_HINT_ICON_PIXMAP) && (icon_pixmap))
+     {
+        *icon_pixmap = xcb_wm_hints_get_icon_pixmap(hints);
+     }
+   if ((flags & XCB_WM_HINT_ICON_MASK) && (icon_mask))
+     {
+        *icon_mask = xcb_wm_hints_get_icon_mask(hints);
+     }
+   if ((flags & XCB_WM_HINT_ICON_WINDOW) && (icon_window))
+     {
+        *icon_window = xcb_wm_hints_get_icon_window(hints);
+     }
+   if ((flags & XCB_WM_HINT_WINDOW_GROUP) && (window_group))
+     {
+        if (reply->value_len < XCB_NUM_WM_HINTS_ELEMENTS)
+           *window_group = 0;
+        else
+           *window_group = xcb_wm_hints_get_window_group(hints);
+     }
+   if ((flags & XCB_WM_HINT_X_URGENCY) && (is_urgent))
+     {
+        *is_urgent = 1;
+     }
+
+   return 1;
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_size_pos_hints_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_NORMAL_HINTS,
+                                       ECORE_X_ATOM_WM_SIZE_HINTS,
+                                       0L, 18);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_size_pos_hints_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_size_pos_hints_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Sets the hints of a window.
+ * @param window      The window.
+ * @param request_pos Request position flag.
+ * @param gravity     Gravity.
+ * @param min_w       Minimum width.
+ * @param min_h       Minimum height.
+ * @param max_w       Maximum width.
+ * @param max_h       Maximum height.
+ * @param base_w      Base width
+ * @param base_h      Base height
+ * @param step_x      X step coordinate.
+ * @param step_y      Y step coordinate.
+ * @param min_aspect  Minimum aspect ratio.
+ * @param max_aspect  Maximum aspect ratio.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_size_pos_hints_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_size_pos_hints_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_size_pos_hints_set(Ecore_X_Window  window,
+                                 int             request_pos,
+                                Ecore_X_Gravity gravity,
+                                int             min_w,
+                                 int             min_h,
+                                int             max_w,
+                                 int             max_h,
+                                int             base_w,
+                                 int             base_h,
+                                int             step_x,
+                                 int             step_y,
+                                double          min_aspect,
+                                 double          max_aspect)
+{
+   xcb_size_hints_t          hint;
+   xcb_get_property_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply                                      ||
+       (reply->type != ECORE_X_ATOM_WM_SIZE_HINTS) ||
+       ((reply->format != 8)   &&
+        (reply->format != 16)  &&
+        (reply->format != 32))                     ||
+       (reply->value_len < 15))
+      return;
+
+   xcb_size_hints_set_flags(&hint, 0);
+   if (request_pos)
+     {
+       xcb_size_hints_set_flags(&hint, XCB_SIZE_HINT_US_POSITION);
+     }
+   if (gravity != ECORE_X_GRAVITY_NW)
+     {
+       xcb_size_hints_set_win_gravity(&hint, (uint8_t)gravity);
+     }
+   if ((min_w > 0) || (min_h > 0))
+     {
+       xcb_size_hints_set_min_size(&hint, min_w, min_h);
+     }
+   if ((max_w > 0) || (max_h > 0))
+     {
+       xcb_size_hints_set_max_size(&hint, max_w, max_h);
+     }
+   if ((base_w > 0) || (base_h > 0))
+     {
+       xcb_size_hints_set_base_size(&hint, base_w, base_h);
+     }
+   if ((step_x > 1) || (step_y > 1))
+     {
+       xcb_size_hints_set_resize_inc(&hint, step_x, step_y);
+     }
+   if ((min_aspect > 0.0) || (max_aspect > 0.0))
+     {
+       xcb_size_hints_set_aspect(&hint,
+                                  (int32_t)(min_aspect * 10000),
+                                  10000,
+                                  (int32_t)(max_aspect * 10000),
+                                  10000);
+     }
+   xcb_set_wm_normal_hints(_ecore_xcb_conn, window, &hint);
+}
+
+/**
+ * Gets the hints of a window.
+ * @param window      The window.
+ * @param request_pos Request position flag.
+ * @param gravity     Gravity.
+ * @param min_w       Minimum width.
+ * @param min_h       Minimum height.
+ * @param max_w       Maximum width.
+ * @param max_h       Maximum height.
+ * @param base_w      Base width
+ * @param base_h      Base height
+ * @param step_x      X step coordinate.
+ * @param step_y      Y step coordinate.
+ * @param min_aspect  Minimum aspect ratio.
+ * @param max_aspect  M
+ * @return            1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_size_pos_hints_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_size_pos_hints_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI int
+ecore_x_icccm_size_pos_hints_get(Ecore_X_Window   window __UNUSED__,
+                                 int             *request_pos,
+                                 Ecore_X_Gravity *gravity,
+                                 int             *min_w,
+                                 int             *min_h,
+                                 int             *max_w,
+                                 int             *max_h,
+                                 int             *base_w,
+                                 int             *base_h,
+                                 int             *step_x,
+                                 int             *step_y,
+                                 double          *min_aspect,
+                                 double          *max_aspect)
+{
+   xcb_size_hints_t          hint;
+   xcb_get_property_reply_t *reply;
+   uint32_t                  flags;
+   int32_t                   minw = 0;
+   int32_t                   minh = 0;
+   int32_t                   maxw = 32767;
+   int32_t                   maxh = 32767;
+   int32_t                   basew = -1;
+   int32_t                   baseh = -1;
+   int32_t                   stepx = -1;
+   int32_t                   stepy = -1;
+   double                    mina = 0.0;
+   double                    maxa = 0.0;
+
+   if (request_pos) *request_pos = 0;
+   if (gravity) *gravity = ECORE_X_GRAVITY_NW;
+   if (min_w) *min_w = minw;
+   if (min_h) *min_h = minh;
+   if (max_w) *max_w = maxw;
+   if (max_h) *max_h = maxh;
+   if (base_w) *base_w = basew;
+   if (base_h) *base_h = baseh;
+   if (step_x) *step_x = stepx;
+   if (step_y) *step_y = stepy;
+   if (min_aspect) *min_aspect = mina;
+   if (max_aspect) *max_aspect = maxa;
+
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   if (!_ecore_x_icccm_size_hints_get(reply, ECORE_X_ATOM_WM_NORMAL_HINTS, &hint))
+     return 0;
+
+   flags = xcb_size_hints_get_flags(hint);
+     if ((flags & XCB_SIZE_HINT_US_POSITION) || (flags & XCB_SIZE_HINT_P_POSITION))
+     {
+       if (request_pos)
+          *request_pos = 1;
+     }
+   if (flags & XCB_SIZE_HINT_P_WIN_GRAVITY)
+     {
+       if (gravity)
+          *gravity = xcb_size_hints_get_win_gravity(&hint);
+     }
+   if (flags & XCB_SIZE_HINT_P_MIN_SIZE)
+     {
+       xcb_size_hints_get_min_size(hint, &minw, &minh);
+     }
+   if (flags & XCB_SIZE_HINT_P_MAX_SIZE)
+     {
+       xcb_size_hints_get_max_size(&hint, &maxw, &maxh);
+       if (maxw < minw)
+          maxw = minw;
+       if (maxh < minh)
+          maxh = minh;
+     }
+   if (flags & XCB_SIZE_HINT_BASE_SIZE)
+     {
+       xcb_size_hints_get_base_size(&hint, &basew, &baseh);
+       if (basew > minw)
+          minw = basew;
+       if (baseh > minh)
+          minh = baseh;
+     }
+   if (flags & XCB_SIZE_HINT_P_RESIZE_INC)
+     {
+       xcb_size_hints_get_increase(&hint, &stepx, &stepy);
+       if (stepx < 1)
+          stepx = 1;
+       if (stepy < 1)
+          stepy = 1;
+     }
+   if (flags & XCB_SIZE_HINT_P_ASPECT)
+     {
+        int32_t min_aspect_num;
+        int32_t min_aspect_den;
+        int32_t max_aspect_num;
+        int32_t max_aspect_den;
+
+        xcb_size_hints_get_min_aspect(hint, &min_aspect_num, &min_aspect_den);
+       if (min_aspect_den > 0)
+          mina = ((double)min_aspect_num) / ((double)min_aspect_den);
+        xcb_size_hints_get_max_aspect(hint, &max_aspect_num, &max_aspect_den);
+       if (max_aspect_den > 0)
+          maxa = ((double)max_aspect_num) / ((double)max_aspect_den);
+     }
+
+   if (min_w)
+      *min_w = minw;
+   if (min_h)
+      *min_h = minh;
+   if (max_w)
+      *max_w = maxw;
+   if (max_h)
+      *max_h = maxh;
+   if (base_w)
+      *base_w = basew;
+   if (base_h)
+      *base_h = baseh;
+   if (step_x)
+      *step_x = stepx;
+   if (step_y)
+      *step_y = stepy;
+   if (min_aspect)
+      *min_aspect = mina;
+   if (max_aspect)
+      *max_aspect = maxa;
+
+   return 1;
+}
+
+/**
+ * Set the title of a window
+ * @param window The window.
+ * @param title  The title.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_title_set(Ecore_X_Window window,
+                        const char    *title)
+{
+   if (!title) return;
+
+   /* FIXME: to do:  utf8 */
+
+/*    xprop.value = NULL; */
+/* #ifdef X_HAVE_UTF8_STRING */
+/*    list[0] = strdup(t); */
+/*    ret = */
+/*       Xutf8TextListToTextProperty(_ecore_xcb_conn, list, 1, XUTF8StringStyle, */
+/*                               &xprop); */
+/* #else */
+/*    list[0] = strdup(t); */
+/*    ret = */
+/*       XmbTextListToTextProperty(_ecore_xcb_conn, list, 1, XStdICCTextStyle, */
+/*                             &xprop); */
+/* #endif */
+
+  xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                      ECORE_X_ATOM_WM_NAME, ECORE_X_ATOM_STRING, 8,
+                      strlen(title), title);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_title_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_NAME,
+                                       XCB_GET_PROPERTY_TYPE_ANY,
+                                       0L, 128);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_title_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_title_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Gets the title of a window.
+ * @param window The window (Unused).
+ * @return       The title of the window
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_title_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_title_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI char *
+ecore_x_icccm_title_get(Ecore_X_Window window __UNUSED__)
+{
+   char                     *title = NULL;
+   xcb_get_property_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return NULL;
+
+   if (reply->type == ECORE_X_ATOM_UTF8_STRING)
+     {
+        int length;
+
+        /* FIXME: verify the value of length */
+        length = (reply->value_len * reply->format) / 8;
+        title = (char *)malloc((length + 1) * sizeof(char));
+        memcpy(title, xcb_get_property_value(reply), length);
+        title[length] = '\0';
+     }
+   /* not in UTF8, so we convert */
+   else
+     {
+       /* convert to utf8 */
+
+       /* FIXME: to do... */
+
+/* #ifdef X_HAVE_UTF8_STRING */
+/*              ret = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xprop, */
+/*                                                &list, &num); */
+/* #else */
+/*              ret = XmbTextPropertyToTextList(_ecore_xcb_conn, &xprop, */
+/*                                              &list, &num); */
+/* #endif */
+
+/*              if ((ret == XLocaleNotSupported) || */
+/*                  (ret == XNoMemory) || (ret == XConverterNotFound)) */
+/*                { */
+/*                   t = strdup((char *)xprop.value); */
+/*                } */
+/*              else if ((ret >= Success) && (num > 0)) */
+/*                { */
+/*                   t = strdup(list[0]); */
+/*                } */
+/*              if (list) */
+/*                XFreeStringList(list); */
+/*           } */
+
+/*         if (xprop.value) XFree(xprop.value); */
+     }
+
+   return title;
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_protocol_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_PROTOCOLS,
+                                       ECORE_X_ATOM_ATOM, 0, 1000000L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_protocol_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_protocol_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Set or unset a wm protocol property.
+ * @param window   The Window
+ * @param protocol The protocol to enable/disable
+ * @param on       On/Off
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_protocol_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_protocol_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_protocol_set(Ecore_X_Window      window,
+                          Ecore_X_WM_Protocol protocol,
+                           int                 on)
+{
+   xcb_get_property_reply_t *reply;
+   Ecore_X_Atom             *protos = NULL;
+   Ecore_X_Atom              proto;
+   uint32_t                  protos_count = 0;
+   uint8_t                   already_set = 0;
+
+   /* Check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+      return;
+
+   proto = _ecore_xcb_atoms_wm_protocols[protocol];
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   if ((reply->type == ECORE_X_ATOM_ATOM) && (reply->format == 32))
+     {
+        uint32_t i;
+
+        protos_count = reply->value_len / sizeof(Ecore_X_Atom);
+        protos = (Ecore_X_Atom *)xcb_get_property_value(reply);
+        for (i = 0; i < protos_count; i++)
+          {
+             if (protos[i] == proto)
+               {
+                  already_set = 1;
+                  break;
+               }
+          }
+     }
+
+   if (on)
+     {
+       Ecore_X_Atom *new_protos = NULL;
+
+       if (already_set)
+          return;
+       new_protos = (Ecore_X_Atom *)malloc((protos_count + 1) * sizeof(Ecore_X_Atom));
+       if (!new_protos)
+          return;
+        memcpy(new_protos, protos, reply->value_len);
+       new_protos[protos_count] = proto;
+       xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                            ECORE_X_ATOM_WM_PROTOCOLS,
+                            ECORE_X_ATOM_ATOM, 32,
+                            protos_count + 1, new_protos);
+       free(new_protos);
+     }
+   else
+     {
+        uint32_t i;
+
+       if (!already_set)
+          return;
+       for (i = 0; i < protos_count; i++)
+         {
+            if (protos[i] == proto)
+              {
+                 uint32_t j;
+
+                 for (j = i + 1; j < protos_count; j++)
+                    protos[j - 1] = protos[j];
+                 if (protos_count > 1)
+                     xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                                         ECORE_X_ATOM_WM_PROTOCOLS,
+                                         ECORE_X_ATOM_ATOM, 32,
+                                         protos_count - 1, protos);
+                 else
+                    xcb_delete_property(_ecore_xcb_conn, window,
+                                         ECORE_X_ATOM_WM_PROTOCOLS);
+                 return;
+              }
+         }
+     }
+}
+
+/**
+ * Determines whether a protocol is set for a window.
+ * @param window   The Window (Unused).
+ * @param protocol The protocol to query.
+ * @return         1 if the protocol is set, else 0.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_protocol_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_protocol_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI int
+ecore_x_icccm_protocol_isset(Ecore_X_Window      window __UNUSED__,
+                             Ecore_X_WM_Protocol protocol)
+{
+   xcb_get_property_reply_t *reply;
+   Ecore_X_Atom           *protos = NULL;
+   Ecore_X_Atom            proto;
+   uint32_t                  i;
+   uint8_t                   ret = 0;
+
+   /* check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+      return 0;
+
+   proto = _ecore_xcb_atoms_wm_protocols[protocol];
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply || (reply->type != ECORE_X_ATOM_ATOM) || (reply->format != 32))
+     {
+        return 0;
+     }
+
+   protos = (Ecore_X_Atom *)xcb_get_property_value(reply);
+   for (i = 0; i < reply->value_len; i++)
+      if (protos[i] == proto)
+       {
+          ret = 1;
+          break;
+       }
+
+   return ret;
+}
+
+/**
+ * Set a window name & class.
+ * @param window The window
+ * @param name   The name string
+ * @param class  The class string
+ *
+ * Set the name and class of @p window to respectively @p name and @p class.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_name_class_set(Ecore_X_Window window,
+                             const char    *name,
+                             const char    *class)
+{
+   char *class_string;
+   char *s;
+   int   length_name;
+   int   length_class;
+
+   length_name = strlen(name);
+   length_class = strlen(class);
+   class_string = (char *)malloc(sizeof(char) * (length_name + length_class + 2));
+   if (!class_string)
+     return;
+   s = class_string;
+   if (length_name)
+     {
+       strcpy(s, name);
+       s += length_name + 1;
+     }
+   else
+     *s++ = '\0';
+   if(length_class)
+     strcpy(s, class);
+   else
+     *s = '\0';
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_CLASS, ECORE_X_ATOM_STRING, 8,
+                       length_name + length_class + 2, (void *)class_string);
+   free(class_string);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_name_class_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_CLASS,
+                                       ECORE_X_ATOM_STRING,
+                                       0, 2048L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_name_class_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_name_class_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get a window name and class.
+ * @param window The window (Unused).
+ * @param name   The name string.
+ * @param class  The class string.
+ *
+ * Store the name and class of @p window into respectively @p name and
+ * @p class.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_name_class_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_name_class_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_name_class_get(Ecore_X_Window window __UNUSED__,
+                             char         **name,
+                             char         **class)
+{
+   xcb_get_property_reply_t *reply;
+   void                     *data;
+   char                     *n = NULL;
+   char                     *c = NULL;
+   int                       length;
+   int                       length_name;
+   int                       length_class;
+
+
+   if (name) *name = NULL;
+   if (class) *class = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return;
+
+   if ((reply->type != ECORE_X_ATOM_STRING) ||
+       (reply->format != 8))
+      return;
+
+   length = reply->value_len;
+   data = xcb_get_property_value(reply);
+   /* data contains the name string and the class string */
+   /* separated by the NULL character. data is not NULL-terminated */
+   length_name = strlen(data);
+   n = (char *)malloc(sizeof(char) * (length_name + 1));
+   if (!n)
+      return;
+   length_class = length - length_name - 1;
+   c = (char *)malloc(sizeof(char) * (length_class + 1));
+   if (!c)
+     {
+        free(n);
+        return;
+     }
+
+   memcpy(n, data, length_name);
+   n[length_name] = '\0';
+   length_class = length - length_name - 1;
+   data += length_name + 1;
+   memcpy(c, data, length_class);
+   c[length_class] = '\0';
+
+   if (name)
+      *name = n;
+   if (class)
+      *class = c;
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_client_machine_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_WM_CLIENT_MACHINE,
+                                       XCB_GET_PROPERTY_TYPE_ANY,
+                                       0L, 1000000L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_client_machine_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_client_machine_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get a window client machine string.
+ * @param window The window
+ * @return The windows client machine string
+ *
+ * Return the client machine of a window. String must be free'd when done with.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_client_machine_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_client_machine_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI char *
+ecore_x_icccm_client_machine_get(Ecore_X_Window window)
+{
+   char *name;
+
+   name = ecore_x_window_prop_string_get(window, ECORE_X_ATOM_WM_CLIENT_MACHINE);
+   return name;
+}
+
+/**
+ * Sets the WM_COMMAND property for @a win.
+ *
+ * @param window The window.
+ * @param argc   Number of arguments.
+ * @param argv   Arguments.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_command_set(Ecore_X_Window window,
+                          int            argc,
+                          char         **argv)
+{
+   void *buf;
+   char *b;
+   int   nbytes;
+   int   i;
+
+   for (i = 0, nbytes = 0; i < argc; i++)
+     {
+        nbytes += strlen(argv[i]) + 1;
+     }
+   buf = malloc(sizeof(char) * nbytes);
+   if (!buf)
+     return;
+   b = (char *)buf;
+   for (i = 0; i < argc; i++)
+     {
+        if (argv[i])
+          {
+             strcpy(b, argv[i]);
+             b += strlen(argv[i]) + 1;
+          }
+        else
+          *b++ = '\0';
+     }
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_COMMAND, ECORE_X_ATOM_STRING, 8,
+                       nbytes, buf);
+   free(buf);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_command_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_COMMAND,
+                                       XCB_GET_PROPERTY_TYPE_ANY,
+                                       0L, 1000000L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_command_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_command_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the WM_COMMAND property for a window.
+ *
+ * @param win  The window.
+ * @param argc Number of arguments.
+ * @param argv Arguments.
+ *
+ * Return the command of @p window and store it in @p argv. @p argc
+ * contains the number of arguments. String must be free'd when done with.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_command_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_command_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_command_get(Ecore_X_Window window __UNUSED__,
+                          int           *argc,
+                          char        ***argv)
+{
+   xcb_get_property_reply_t *reply;
+   char                    **v;
+   char                     *data;
+   char                     *cp;
+   char                     *start;
+   uint32_t                  value_len;
+   int                       c;
+   int                       i;
+   int                       j;
+
+   if (argc) *argc = 0;
+   if (argv) *argv = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return;
+
+   if ((reply->type != ECORE_X_ATOM_STRING) ||
+       (reply->format != 8))
+      return;
+
+   value_len = reply->value_len;
+   data = (char *)xcb_get_property_value(reply);
+   if (value_len && (data[value_len - 1] == '\0'))
+     value_len--;
+
+   c = 1;
+   for (cp = (char *)data, i = value_len; i > 0; cp++, i--)
+     {
+        if (*cp == '\0') c++;
+     }
+   v = (char **)malloc((c + 1) * sizeof(char *));
+   if (!v)
+      return;
+
+   start = (char *)malloc((value_len + 1) * sizeof(char));
+   if (!start)
+     {
+       free(v);
+       return;
+     }
+
+    memcpy (start, (char *) data, value_len);
+    start[value_len] = '\0';
+    for (cp = start, i = value_len + 1, j = 0; i > 0; cp++, i--) {
+       if (*cp == '\0') {
+           v[j] = start;
+           start = (cp + 1);
+           j++;
+       }
+    }
+
+   if (c < 1)
+     {
+       if (v)
+         free(v);
+       return;
+     }
+
+   if (argc) *argc = c;
+   if (argv)
+     {
+       (*argv) = malloc(c * sizeof(char *));
+       if (!*argv)
+         {
+            free(v);
+            if (argc) *argc = 0;
+            return;
+         }
+       for (i = 0; i < c; i++)
+         {
+            if (v[i])
+              (*argv)[i] = strdup(v[i]);
+            else
+              (*argv)[i] = strdup("");
+         }
+     }
+
+   free(v);
+}
+
+/**
+ * Set a window icon name.
+ * @param window The window.
+ * @param title  The icon name string.
+ *
+ * Set @p window icon name.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_icon_name_set(Ecore_X_Window window,
+                            const char    *title)
+{
+   /* FIXME: do the UTF8 conversion... */
+
+/* #ifdef X_HAVE_UTF8_STRING */
+/*    list[0] = strdup(t); */
+/*    ret = Xutf8TextListToTextProperty(_ecore_xcb_conn, list, 1, */
+/*                                  XUTF8StringStyle, &xprop); */
+/* #else */
+/*    list[0] = strdup(t); */
+/*    ret = XmbTextListToTextProperty(_ecore_xcb_conn, list, 1, */
+/*                                XStdICCTextStyle, &xprop); */
+/* #endif */
+
+  xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                      ECORE_X_ATOM_WM_ICON_NAME, ECORE_X_ATOM_WM_ICON_NAME,
+                      8, strlen(title), title);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_icon_name_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_ICON_NAME,
+                                       XCB_GET_PROPERTY_TYPE_ANY,
+                                       0L, 128L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_icon_name_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_icon_name_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get a window icon name.
+ * @param window The window.
+ * @return       The windows icon name string.
+ *
+ * Return the icon name of @p window. String must be free'd when done with.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_icon_name_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_icon_name_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI char *
+ecore_x_icccm_icon_name_get(Ecore_X_Window window __UNUSED__)
+{
+   xcb_get_property_reply_t *reply;
+   char                     *title = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return NULL;
+
+   ERR("reply->bytes_afer (should be 0): %d", ((xcb_get_property_reply_t *)reply)->bytes_after);
+
+   if (reply->type == ECORE_X_ATOM_UTF8_STRING)
+     {
+        int length;
+
+        /* FIXME: verify the value of length */
+        length = reply->value_len * reply->format / 8;
+        title = (char *)malloc((length + 1) * sizeof(char));
+        memcpy(title, xcb_get_property_value(reply), length);
+        title[length] = '\0';
+     }
+   /* not in UTF8, so we convert */
+   else
+     {
+        /* FIXME: do the UTF8... */
+
+       /* convert to utf8 */
+/* #ifdef X_HAVE_UTF8_STRING */
+/*               ret = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xprop, */
+/*                                                 &list, &num); */
+/* #else */
+/*               ret = XmbTextPropertyToTextList(_ecore_xcb_conn, &xprop, */
+/*                                               &list, &num); */
+/* #endif */
+
+/*               if ((ret == XLocaleNotSupported) || */
+/*                   (ret == XNoMemory) || (ret == XConverterNotFound)) */
+/*                 { */
+/*                    t = strdup((char *)xprop.value); */
+/*                 } */
+/*               else if (ret >= Success) */
+/*                 { */
+/*                    if ((num >= 1) && (list)) */
+/*                      { */
+/*                         t = strdup(list[0]); */
+/*                      } */
+/*                    if (list) */
+/*                      XFreeStringList(list); */
+/*                 } */
+/*            } */
+
+/*          if (xprop.value) XFree(xprop.value); */
+     }
+
+   return title;
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_colormap_window_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? ((xcb_screen_t *)_ecore_xcb_screen)->root : window,
+                                       ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                       ECORE_X_ATOM_WINDOW,
+                                       0L, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_colormap_window_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_colormap_window_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Add a subwindow to the list of windows that need a different colormap installed.
+ * @param window     The toplevel window
+ * @param sub_window The subwindow to be added to the colormap windows list
+ *
+ * Add @p sub_window to the list of windows that need a different
+ * colormap installed.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_colormap_window_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_colormap_window_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_colormap_window_set(Ecore_X_Window window,
+                                  Ecore_X_Window sub_window)
+{
+   void                     *data = NULL;
+   xcb_get_property_reply_t *reply;
+   uint32_t                  num;
+
+   if (window == 0)
+     window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply || (reply->format != 32) || (reply->value_len == 0))
+     {
+        data = calloc(1, sizeof(Ecore_X_Window));
+        if (!data)
+          {
+             if (reply) free(reply);
+             return;
+          }
+        num = 1;
+     }
+   else
+     {
+        Ecore_X_Window *newset = NULL;
+        Ecore_X_Window *oldset = NULL;
+        uint32_t          i;
+
+        num = reply->value_len;
+        data = calloc(num + 1, sizeof(Ecore_X_Window));
+        if (!data)
+          return;
+
+        newset = (Ecore_X_Window *)data;
+        oldset = (Ecore_X_Window *)xcb_get_property_value(reply);
+        for (i = 0; i < num; ++i)
+          {
+             if (oldset[i] == sub_window)
+               {
+                  free(newset);
+                  return;
+               }
+
+             newset[i] = oldset[i];
+          }
+
+        newset[num++] = sub_window;
+     }
+
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                       ECORE_X_ATOM_WINDOW,
+                       32, num, data);
+   free(data);
+}
+
+/**
+ * Remove a window from the list of colormap windows.
+ * @param window     The toplevel window
+ * @param sub_window The window to be removed from the colormap window list.
+ *
+ * Remove @p sub_window from the list of colormap windows.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_colormap_window_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_colormap_window_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_colormap_window_unset(Ecore_X_Window window,
+                                    Ecore_X_Window sub_window)
+{
+   void                     *data = NULL;
+   Ecore_X_Window           *oldset = NULL;
+   Ecore_X_Window           *newset = NULL;
+   xcb_get_property_reply_t *reply;
+   uint32_t                  num;
+   uint32_t                  i;
+   uint32_t                  j;
+   uint32_t                  k = 0;
+
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply || (reply->format != 32) || (reply->value_len == 0))
+     return;
+
+   num = reply->value_len;
+   oldset = (Ecore_X_Window *)xcb_get_property_value(reply);
+   for (i = 0; i < num; i++)
+     {
+       if (oldset[i] == sub_window)
+         {
+            if (num == 1)
+              {
+                 xcb_delete_property(_ecore_xcb_conn, window,
+                                      ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
+                 return;
+              }
+            else
+              {
+                 data = calloc(num - 1, sizeof(Ecore_X_Window));
+                 newset = (Ecore_X_Window *)data;
+                 for (j = 0; j < num; ++j)
+                    if (oldset[j] != sub_window)
+                       newset[k++] = oldset[j];
+                  xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                                      ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                      ECORE_X_ATOM_WINDOW,
+                                      32, k, data);
+                 free(newset);
+                 return;
+              }
+         }
+     }
+}
+
+/**
+ * Specify that a window is transient for another top-level window and should be handled accordingly.
+ * @param window    The transient window
+ * @param forwindow The toplevel window
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_transient_for_set(Ecore_X_Window window,
+                                Ecore_X_Window forwindow)
+{
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_TRANSIENT_FOR, ECORE_X_ATOM_WINDOW, 32,
+                       1, (void *)&forwindow);
+}
+
+/**
+ * Remove the transient_for setting from a window.
+ * @param window The window.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_transient_for_unset(Ecore_X_Window window)
+{
+   xcb_delete_property(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_TRANSIENT_FOR);
+}
+
+/*
+ * Sends the GetProperty request.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_transient_for_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_WM_TRANSIENT_FOR,
+                                       ECORE_X_ATOM_WINDOW,
+                                       0L, 1L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_transient_for_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_transient_for_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the window this window is transient for, if any.
+ * @param window The window to check (Unused).
+ * @return       The window ID of the top-level window, or 0 if the property does not exist.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_transient_for_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_transient_for_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_icccm_transient_for_get(Ecore_X_Window window __UNUSED__)
+{
+   xcb_get_property_reply_t *reply;
+   Ecore_X_Window            forwin = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return forwin;
+
+   if ((reply->format != 32) ||
+       (reply->value_len == 0) ||
+       (reply->type != ECORE_X_ATOM_WINDOW))
+      return forwin;
+   
+   forwin = *(Ecore_X_Window *)xcb_get_property_value(reply);
+
+   return forwin;
+}
+
+/**
+ * Set the window role hint.
+ * @param window The window
+ * @param role   The role string.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_window_role_set(Ecore_X_Window window,
+                              const char    *role)
+{
+   ecore_x_window_prop_string_set(window, ECORE_X_ATOM_WM_WINDOW_ROLE,
+                                 (char *)role);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_window_role_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_WM_WINDOW_ROLE, XCB_GET_PROPERTY_TYPE_ANY,
+                                       0L, 1000000L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_window_role_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_window_role_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the window role.
+ * @param window The window.
+ * @return       The window's role string.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_window_role_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_window_role_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI char *
+ecore_x_icccm_window_role_get(Ecore_X_Window window)
+{
+   return ecore_x_window_prop_string_get(window, ECORE_X_ATOM_WM_WINDOW_ROLE);
+}
+
+/**
+ * Set the window's client leader.
+ * @param window The window
+ * @param leader The client leader window
+ *
+ * All non-transient top-level windows created by an app other than
+ * the main window must have this property set to the app's main window.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_client_leader_set(Ecore_X_Window window,
+                                Ecore_X_Window leader)
+{
+   ecore_x_window_prop_window_set(window, ECORE_X_ATOM_WM_CLIENT_LEADER,
+                                 &leader, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_client_leader_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window,
+                                       ECORE_X_ATOM_WM_CLIENT_LEADER,
+                                       ECORE_X_ATOM_WINDOW,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_icccm_client_leader_get_prefetch().
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_client_leader_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the window's client leader.
+ * @param window The window
+ * @return       The window's client leader window, or 0 if unset.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_icccm_client_leader_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_icccm_client_leader_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_icccm_client_leader_get(Ecore_X_Window window)
+{
+   Ecore_X_Window leader;
+
+   if (ecore_x_window_prop_window_get(window, ECORE_X_ATOM_WM_CLIENT_LEADER,
+                                     &leader, 1) > 0)
+      return leader;
+
+   return 0;
+}
+
+/**
+ * Send the ClientMessage event with the ChangeState property.
+ * @param window The window.
+ * @param root   The root window.
+ * @ingroup Ecore_X_ICCCM_Group
+ */
+EAPI void
+ecore_x_icccm_iconic_request_send(Ecore_X_Window window,
+                                  Ecore_X_Window root)
+{
+   xcb_client_message_event_t ev;
+
+   if (!window) return;
+   if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   /* send_event is bit 7 (0x80) of response_type */
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.sequence = 0;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_WM_CHANGE_STATE;
+   ev.data.data32[0] = XCB_WM_STATE_ICONIC;
+
+   xcb_send_event(_ecore_xcb_conn, 0, root,
+                  XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+                  (const char *)&ev);
+}
+
+/* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */
+/*        hints. each should go in their own file/section so we know which */
+/*        is which. also older kde hints too. we should try support as much */
+/*        as makese sense to support */
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_mwm.c b/src/lib/ecore_x/xcb/ecore_xcb_mwm.c
new file mode 100644 (file)
index 0000000..f96c4cf
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Various MWM related functions.
+ * 
+ * This is ALL the code involving anything MWM related. for both WM and
+ * client.
+ */
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+/**
+ * @defgroup Ecore_X_MWM_Group MWM related functions.
+ *
+ * Functions related to MWM.
+ */
+
+#define ECORE_X_MWM_HINTS_FUNCTIONS           (1 << 0)
+#define ECORE_X_MWM_HINTS_DECORATIONS         (1 << 1)
+#define ECORE_X_MWM_HINTS_INPUT_MODE          (1 << 2)
+#define ECORE_X_MWM_HINTS_STATUS              (1 << 3)
+
+typedef struct _mwmhints
+{
+   uint32_t flags;
+   uint32_t functions;
+   uint32_t decorations;
+   int32_t  inputmode;
+   uint32_t status;
+}
+MWMHints;
+
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose MWM hints are requested.
+ * @ingroup Ecore_X_MWM_Group
+ */
+EAPI void
+ecore_x_mwm_hints_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                       ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                       0, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_mwm_hints_get_prefetch().
+ * @ingroup Ecore_X_MWM_Group
+ */
+EAPI void
+ecore_x_mwm_hints_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * To document.
+ * @param  window Unused.
+ * @param  fhint To document.
+ * @param  dhint To document.
+ * @param  ihint To document.
+ * @return       1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_mwm_hints_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_mwm_hints_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_MWM_Group
+ */
+EAPI int
+ecore_x_mwm_hints_get(Ecore_X_Window          window __UNUSED__,
+                     Ecore_X_MWM_Hint_Func  *fhint,
+                     Ecore_X_MWM_Hint_Decor *dhint,
+                     Ecore_X_MWM_Hint_Input *ihint)
+{
+   MWMHints                 *mwmhints = NULL;
+   int                       ret = 0;
+   xcb_get_property_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return 0;
+
+   if ((reply->format != 32) ||
+       (reply->value_len == 0))
+      return 0;
+
+   mwmhints = xcb_get_property_value(reply);
+   if (reply->value_len >= 4)
+     {
+        if (dhint)
+          {
+             if (mwmhints->flags & ECORE_X_MWM_HINTS_DECORATIONS)
+               *dhint = mwmhints->decorations;
+             else
+               *dhint = ECORE_X_MWM_HINT_DECOR_ALL;
+          }
+        if (fhint)
+          {
+             if (mwmhints->flags & ECORE_X_MWM_HINTS_FUNCTIONS)
+               *fhint = mwmhints->functions;
+             else
+               *fhint = ECORE_X_MWM_HINT_FUNC_ALL;
+          }
+        if (ihint)
+          {
+             if (mwmhints->flags & ECORE_X_MWM_HINTS_INPUT_MODE)
+               *ihint = mwmhints->inputmode;
+             else
+               *ihint = ECORE_X_MWM_HINT_INPUT_MODELESS;
+          }
+        ret = 1;
+     }
+
+   return ret;
+}
+
+/**
+ * Sets the borderless flag of a window using MWM.
+ * @param window     The window.
+ * @param borderless The borderless flag.
+ * @ingroup Ecore_X_MWM_Group
+ */
+EAPI void
+ecore_x_mwm_borderless_set(Ecore_X_Window window,
+                           int            borderless)
+{
+   uint32_t data[5] = {0, 0, 0, 0, 0};
+
+   data[0] = 2; /* just set the decorations hint! */
+   data[2] = !borderless;
+   
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_MOTIF_WM_HINTS, ECORE_X_ATOM_MOTIF_WM_HINTS,
+                       32, 5, data);
+}
+
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_netwm.c b/src/lib/ecore_x/xcb/ecore_xcb_netwm.c
new file mode 100644 (file)
index 0000000..e9a76e5
--- /dev/null
@@ -0,0 +1,3197 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+/**
+ * @defgroup Ecore_X_NetWM_Group Extended Window Manager Hint (EWMH) functions
+ *
+ * Functions related to the Extended Window Manager Hint (EWMH).
+ */
+
+
+typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
+
+struct _Ecore_X_Startup_Info
+{
+   Ecore_X_Window win;
+
+   int   init;
+
+   int   buffer_size;
+   char *buffer;
+
+   int   length;
+
+   /* These are the sequence info fields */
+   char *id;
+   char *name;
+   int   screen;
+   char *bin;
+   char *icon;
+   int   desktop;
+   int   timestamp;
+   char *description;
+   char *wmclass;
+   int   silent;
+};
+
+#if 0
+static void  _ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window, Ecore_X_Atom atom);
+static void  _ecore_x_window_prop_string_utf8_get_fetch(void);
+#endif
+static void  _ecore_x_window_prop_string_utf8_set(Ecore_X_Window window, Ecore_X_Atom atom, const char *str);
+static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window window, Ecore_X_Atom atom);
+#if 0 /* Unused */
+static int   _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
+static int   _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, char *data);
+#endif
+static void  _ecore_x_netwm_startup_info_free(void *data);
+
+/*
+ * Local variables
+ */
+
+static Eina_Hash *startup_info = NULL;
+
+/**
+ * Initialize the NetWM module
+ */
+EAPI void
+ecore_x_netwm_init(void)
+{
+   startup_info = eina_hash_string_superfast_new(_ecore_x_netwm_startup_info_free);
+}
+
+/**
+ * Shutdown the NetWM module
+ */
+EAPI void
+ecore_x_netwm_shutdown(void)
+{
+   if (startup_info)
+     eina_hash_free(startup_info);
+   startup_info = NULL;
+}
+
+/**
+ * Set the _NET_SUPPORTING_WM_CHECK property.
+ * @param root    The root window.
+ * @param check   The child window.
+ * @param wm_name The name of the Window Manager.
+ *
+ * Set the _NET_SUPPORTING_WM_CHECK property on the @p root window to be
+ * the ID of the child window @p check created by the Window Manager.
+ * @p check also have the _NET_WM_NAME property set to the name
+ * @p wm_name of the Window Manager.
+ *
+ * The Window MUST call that function to indicate that a compliant
+ * window manager is active.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_wm_identify(Ecore_X_Window root,
+                          Ecore_X_Window check,
+                         const char    *wm_name)
+{
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
+   ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
+   _ecore_x_window_prop_string_utf8_set(check, ECORE_X_ATOM_NET_WM_NAME, wm_name);
+   /* This one isn't mandatory */
+   _ecore_x_window_prop_string_utf8_set(root, ECORE_X_ATOM_NET_WM_NAME, wm_name);
+}
+
+/**
+ * Set the _NET_SUPPORTED property.
+ * @param root      The root window.
+ * @param supported The supported hints.
+ * @param num       The number of hints.
+ *
+ * Set the _NET_SUPPORTED property on the @p root window. The hints
+ * that the Window Manager supports are stored in @p supported.
+ *
+ * The Window Manager MUST set this property to indicate which hints
+ * it supports.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_supported_set(Ecore_X_Window root,
+                            Ecore_X_Atom  *supported,
+                            int            num)
+{
+   ecore_x_window_prop_atom_set(root, ECORE_X_ATOM_NET_SUPPORTED, supported, num);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param root The root window
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_supported_get_prefetch(Ecore_X_Window root)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, root,
+                                       ECORE_X_ATOM_NET_SUPPORTED, ECORE_X_ATOM_ATOM,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_supported_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_supported_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the hints supported by the Window Manager.
+ * @param root      The root window.
+ * @param supported The supported hints.
+ * @param num       The number of atoms.
+ * @return          1 on success, 0 otherwise.
+ *
+ * Get the hints supported by the Window Manager. @p root is the root
+ * window. The hints are stored in @p supported. The number of hints
+ * is stored in @p num.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_supported_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_supported_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_supported_get(Ecore_X_Window root,
+                            Ecore_X_Atom **supported,
+                            int           *num)
+{
+   int num_ret;
+
+   if (num) *num = 0UL;
+   if (supported) *supported = NULL;
+
+   num_ret = ecore_x_window_prop_xid_list_get(root,
+                                              ECORE_X_ATOM_NET_SUPPORTED,
+                                              ECORE_X_ATOM_ATOM,
+                                              supported);
+   if (num_ret <= 0)
+      return 0;
+
+   if (num) *num = (uint32_t)num_ret;
+   return 1;
+}
+
+/**
+ * Set the _NET_NUMBER_OF_DESKTOPS property.
+ * @param root The root window.
+ * @param n_desks The number of desktops.
+ *
+ * Set the number of desktops @p n_desks of the Window Manager by
+ * sending the _NET_NUMBER_OF_DESKTOPS to the @p root window.
+ *
+ * The Window Manager SHOULD set and update this property to indicate
+ * the number of virtual desktops. A Pager can request a change in the
+ * number of desktops by using that function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_count_set(Ecore_X_Window root,
+                             unsigned int   n_desks)
+{
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
+                                 &n_desks, 1);
+}
+
+/**
+ * Set the _NET_VIRTUAL_ROOTS property.
+ * @param root    The root window.
+ * @param vroots  The virtual root windows.
+ * @param n_desks The number of desks.
+ *
+ * Set the number of virtual desktops by sending the
+ * _NET_VIRTUAL_ROOTS property to the @p root window. @p vroots is an
+ * array of window and @p n_desks is the number of windows.
+ *
+ * A Window Manager that implements virtual desktops by reparent
+ * client windows to a child of the root window MUST use that
+ * function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_roots_set(Ecore_X_Window  root,
+                            Ecore_X_Window *vroots,
+                             unsigned int    n_desks)
+{
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots, n_desks);
+}
+
+/**
+ * Set the _NET_DESKTOP_NAMES property.
+ * @param root    The root window.
+ * @param names   The names of the virtual desktops.
+ * @param n_desks The number of virtual desktops.
+ *
+ * Set the name of each virtual desktop by sending the
+ * _NET_DESKTOP_NAMES to the @p root window. @p names are the names of
+ * the virtual desktops and @p n_desks is the number of virtual
+ * desktops.
+ *
+ * A Pager MAY use that function. @p n_desks may be different from the
+ * one passed to ecore_x_netwm_desk_count_set().  If it less or equal,
+ * then the desktops with high numbers are unnamed. If it is larger,
+ * then the excess names are considered to be reserved in case the
+ * number of desktops is increased.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_names_set(Ecore_X_Window root,
+                            const char   **names,
+                             unsigned int   n_desks)
+{
+   char        ss[32];
+   char       *buf;
+   const char *s;
+   uint32_t    i;
+   uint32_t    len;
+   uint32_t    l;
+
+   buf = NULL;
+   len = 0;
+
+   for (i = 0; i < n_desks; i++)
+     {
+       s = (names) ? names[i] : NULL;
+       if (!s)
+         {
+            /* Default to "Desk-<number>" */
+            sprintf(ss, "Desk-%d", i);
+            s = ss;
+         }
+
+       l = strlen(s) + 1;
+       buf = realloc(buf, len + l);
+       memcpy(buf + len, s, l);
+       len += l;
+     }
+
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, root,
+                       ECORE_X_ATOM_NET_DESKTOP_NAMES,
+                       ECORE_X_ATOM_UTF8_STRING,
+                       8, len, (const void *)buf);
+   free(buf);
+}
+
+/**
+ * Set the _NET_DESKTOP_GEOMETRY property.
+ * @param root   The root window.
+ * @param width  The width of the desktop.
+ * @param height The height of the desktop.
+ *
+ * Set the common @p width and @p height of all desktops by sending
+ * the _NET_DESKTOP_GEOMETRY to the @p root window.
+ *
+ * This size is equal to the screen size if the Window Manager doesn't
+ * support large desktops, otherwise it's equal to the virtual size of
+ * the desktop. The Window Manager SHOULD set this property. A Pager
+ * can request a change in the desktop geometry by using this
+ * function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_size_set(Ecore_X_Window root,
+                            unsigned int   width,
+                            unsigned int   height)
+{
+   uint32_t size[2];
+
+   size[0] = width;
+   size[1] = height;
+   ecore_x_window_prop_card32_set(root,
+                                  ECORE_X_ATOM_NET_DESKTOP_GEOMETRY,
+                                  size, 2);
+}
+
+/**
+ * Set the _NET_DESKTOP_VIEWPORT property.
+ * @param root    The root window.
+ * @param origins An array of paris of coordiantes.
+ * @param n_desks The number of virtual desktops.
+ *
+ * Set the top left corner of each desktop's viewport by sending the
+ * _NET_DESKTOP_VIEWPORT property to the @p root window. @p origins
+ * contains each pair of X coordinate and Y coordinate of the top left
+ * corner of each desktop's viewport.
+ *
+ * If the Window Manager does not support large desktops, the
+ * coordinates MUST be (0,0). A Pager can request to change the
+ * viewport for the current desktop by using this function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
+                                 unsigned int  *origins,
+                                 unsigned int   n_desks)
+{
+   ecore_x_window_prop_card32_set(root,
+                                  ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
+                                  origins, 2 * n_desks);
+}
+
+/**
+ * Set the _NET_DESKTOP_LAYOUT property.
+ * @param root The root window.
+ * @param orientation
+ * @param columns
+ * @param rows
+ * @param starting_corner
+ *
+ * Set the layout of virtual desktops relative to each other by
+ * sending the _NET_DESKTOP_LAYOUT to the @p root window.
+ * @p orientation defines the orientation of the virtual desktop. 0
+ * means horizontal layout, 1 means vertical layout. @p columns is
+ * the number of desktops in the X direction and @p rows is the number
+ * in the Y direction. @p starting_corner is the corner containing the
+ * first desktop. The values for @p starting_corner are 0 (top-left),
+ * 1 (top-right), 2 (bottom-right) and 3 (bottom-left).
+ *
+ * When the orientation is horizontal the desktops are laid out in
+ * rows, with the first desktop in the specified starting corner. So a
+ * layout with four columns and three rows starting in
+ * the top-left corner looks like this:
+ *
+ * +--+--+--+--+
+ * | 0| 1| 2| 3|
+ * +--+--+--+--+
+ * | 4| 5| 6| 7|
+ * +--+--+--+--+
+ * | 8| 9|10|11|
+ * +--+--+--+--+
+ *
+ * With @p starting_corner being bottom-right, it looks like this:
+ *
+ * +--+--+--+--+
+ * |11|10| 9| 8|
+ * +--+--+--+--+
+ * | 7| 6| 5| 4|
+ * +--+--+--+--+
+ * | 3| 2| 1| 0|
+ * +--+--+--+--+
+ *
+ * When the orientation is vertical the layout with four columns and
+ * three rows starting in the top-left corner looks like:
+ *
+ * +--+--+--+--+
+ * | 0| 3| 6| 9|
+ * +--+--+--+--+
+ * | 1| 4| 7|10|
+ * +--+--+--+--+
+ * | 2| 5| 8|11|
+ * +--+--+--+--+
+ *
+ * With @p starting_corner  being top-right, it looks like:
+ *
+ * +--+--+--+--+
+ * | 9| 6| 3| 0|
+ * +--+--+--+--+
+ * |10| 7| 4| 1|
+ * +--+--+--+--+
+ * |11| 8| 5| 2|
+ * +--+--+--+--+
+ *
+ * This function MUST be used by a Pager and NOT by the Window
+ * Manager. When using this function, the Pager must own a manager
+ * selection.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_layout_set(Ecore_X_Window root,
+                              int            orientation,
+                              int            columns,
+                              int            rows,
+                              int            starting_corner)
+{
+   uint32_t layout[4];
+
+   layout[0] = orientation;
+   layout[1] = columns;
+   layout[2] = rows;
+   layout[3] = starting_corner;
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT, layout, 4);
+}
+
+/**
+ * Set the _NET_WORKAREA property.
+ * @param root    The root window.
+ * @param areas   An array of areas.
+ * @param n_desks The number of desks.
+ *
+ * Set the work area for each desktop by sending the _NET_WORKAREA
+ * property to the @p root window. An area contains the geometry (X
+ * and Y coordinates, width and height). These geometries are
+ * specified relative to the viewport on each desktop and specify an
+ * area that is completely contained within the viewport. @p areas
+ * stores these geometries. @p n_desks is the number of geometry to
+ * set.
+ *
+ * This function MUST be set by the Window Manager. It is used by
+ * desktop applications to place desktop icons appropriately.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
+                                 unsigned int  *areas,
+                                 unsigned int   n_desks)
+{
+   ecore_x_window_prop_card32_set(root,
+                                  ECORE_X_ATOM_NET_WORKAREA,
+                                  areas, 4 * n_desks);
+}
+
+/**
+ * Set the _NET_CURRENT_DESKTOP property.
+ * @param root The root window.
+ * @param desk The index of the current desktop.
+ *
+ * Set the current desktop by sending the _NET_CURRENT_DESKTOP to the
+ * @p root window. @p deskmust be an integer number between 0 and the
+ * number of desks (set by ecore_x_netwm_desk_count_set()) -1.
+ *
+ * This function MUST be called by the Window Manager. If a Pagerwants
+ * to switch to naother desktop, it MUST call that function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desk_current_set(Ecore_X_Window root,
+                               unsigned int   desk)
+{
+   ecore_x_window_prop_card32_set(root,
+                                  ECORE_X_ATOM_NET_CURRENT_DESKTOP,
+                                  &desk, 1);
+}
+
+/**
+ * Set the _NET_SHOWING_DESKTOP property.
+ * @param root The root window
+ * @param on   0 to hide the desktop, non 0 to show it.
+ *
+ * Set or unset the desktop in a "showing mode" by sending the
+ * _NET_SHOWING_DESKTOP property to the @p root window. If @p on is 0,
+ * the windows are hidden and the desktop background is displayed and
+ * focused.
+ *
+ * If a Pager wants to enter or leave the mode, it MUST use this
+ * function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,
+                                  int            on)
+{
+   uint32_t val;
+
+   val = (on) ? 1 : 0;
+   ecore_x_window_prop_card32_set(root,
+                                  ECORE_X_ATOM_NET_SHOWING_DESKTOP,
+                                  &val, 1);
+}
+
+/*
+ * Client status
+ */
+
+/**
+ * Set the _NET_CLIENT_LIST property.
+ * @param root The root window.
+ * @param p_clients An array of windows.
+ * @param n_clients The number of windows.
+ *
+ * Map all the X windows managed by the window manager from the oldest
+ * to the newest by sending the _NET_CLIENT_LIST property to the
+ * @p root window. The X windows are stored in @p p_clients and their
+ * number in @p n_clients.
+ *
+ * This function SHOULD be called by the Window Manager.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_client_list_set(Ecore_X_Window  root,
+                              Ecore_X_Window *p_clients,
+                              unsigned int    n_clients)
+{
+   ecore_x_window_prop_window_set(root,
+                                  ECORE_X_ATOM_NET_CLIENT_LIST,
+                                  p_clients, n_clients);
+}
+
+/**
+ * Set the _NET_CLIENT_LIST_STACKING property.
+ * @param root The root window.
+ * @param p_clients An array of windows.
+ * @param n_clients The number of windows.
+ *
+ * Stack all the X windows managed by the window manager from bottom
+ * to top order by sending the _NET_CLIENT_LIST_STACKING property to the
+ * @p root window. The X windows are stored in @p p_clients and their
+ * number in @p n_clients.
+ *
+ * This function SHOULD be called by the Window Manager.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_client_list_stacking_set(Ecore_X_Window  root,
+                                       Ecore_X_Window *p_clients,
+                                       unsigned int    n_clients)
+{
+   ecore_x_window_prop_window_set(root,
+                                  ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
+                                  p_clients, n_clients);
+}
+
+/**
+ * Set the _NET_ACTIVE_WINDOW property.
+ * @param root   The root window.
+ * @param window The widow to activate.
+ *
+ * Activate @p window by sending the _NET_ACTIVE_WINDOW property to
+ * the @p root window.
+ *
+ * If a Client wants to activate another window, it MUST call this
+ * function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_client_active_set(Ecore_X_Window root,
+                                Ecore_X_Window window)
+{
+   ecore_x_window_prop_window_set(root,
+                                  ECORE_X_ATOM_NET_ACTIVE_WINDOW,
+                                  &window, 1);
+}
+
+/**
+ * Set the _NET_WM_NAME property.
+ * @param window The widow to activate.
+ * @param name   The title name of the window.
+ *
+ * Set the title name of @p window to @p name by sending the
+ * _NET_WM_NAME property to @p window.
+ *
+ * The Client SHOULD set the title of @p window in UTF-8 encoding. If
+ * set, the Window Manager should use this in preference to WM_NAME.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_name_set(Ecore_X_Window window,
+                       const char    *name)
+{
+   _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_NAME, name);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_name_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_NAME, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_name_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_name_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the title of a window.
+ * @param window The window.
+ * @param name   The title name.
+ * @return       Returns always 1.
+ *
+ * Retrieve the title name of @p window and store it in @p name. The
+ * function returns always 1.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_name_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_name_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_name_get(Ecore_X_Window window,
+                       char         **name)
+{
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_WM_NAME);
+   return 1;
+}
+
+/**
+ * Set the _NET_STARTUP_ID property.
+ * @param window The window.
+ * @param id     The ID name.
+ *
+ * Set the ID @p id used for the startup sequence by sending the
+ * property _NET_STARTUP_ID to @p window. The ID name should be
+ * encoded in UTF-8.
+ *
+ * If a new value for the property is set, the Window Manager
+ * should update the window's status accordingly (update its virtual
+ * desktop, etc.).
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_startup_id_set(Ecore_X_Window window,
+                             const char    *id)
+{
+   _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_STARTUP_ID, id);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_startup_id_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_STARTUP_ID, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_startup_id_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_startup_id_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the startup ID name of a window.
+ * @param window The window
+ * @param id     The ID name
+ * @return       Return always 1.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_startup_id_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_startup_id_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_startup_id_get(Ecore_X_Window window,
+                             char         **id)
+{
+   if (id)
+     *id = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_STARTUP_ID);
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_VISIBLE_NAME property.
+ * @param window The widow to activate.
+ * @param name   The title name of the window.
+ *
+ * Set the title name of @p window to @p name by sending the
+ * _NET_WM_VISIBLE_NAME property to @p window, when the Window Manager
+ * displays a window name other than by calling
+ * ecore_x_netwm_name_set().
+ *
+ * The Client SHOULD set the title of @p window in UTF-8
+ * encoding. This function is used for displaying title windows like
+ * [xterm1], [xterm2], ... thereby allowing Pagers to display the same
+ * title as the Window Manager.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_name_set(Ecore_X_Window window,
+                               const char    *name)
+{
+   _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
+                                        name);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_name_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_VISIBLE_NAME, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_name_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_name_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the visible title of a window.
+ * @param window The window.
+ * @param name   The title name.
+ * @return       Returns always 1.
+ *
+ * Retrieve the visible title name of @p window and store it in @p name. The
+ * function returns always 1.
+ * @param window The window
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_visible_name_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_visible_name_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_visible_name_get(Ecore_X_Window window,
+                               char         **name)
+{
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(window,
+                                                  ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_ICON_NAME property.
+ * @param window The widow to activate.
+ * @param name   The icon name of the window.
+ *
+ * Set the icon name of @p window to @p name by sending the
+ * _NET_WM_ICON_NAME property to @p window.
+ *
+ * The Client SHOULD set the title of @p window in UTF-8 encoding. If
+ * set, the Window Manager should use this in preference to WM_ICON_NAME.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_name_set(Ecore_X_Window window,
+                            const char    *name)
+{
+   _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_ICON_NAME,
+                                        name);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_name_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_ICON_NAME, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_icon_name_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_name_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the icon name of a window.
+ * @param window The window.
+ * @param name   The icon name.
+ * @return       Returns always 1.
+ *
+ * Retrieve the icon name of @p window and store it in @p name. The
+ * function returns always 1.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_icon_name_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_icon_name_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_icon_name_get(Ecore_X_Window window,
+                            char         **name)
+{
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(window,
+                                                 ECORE_X_ATOM_NET_WM_ICON_NAME);
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_VISIBLE_ICON_NAME property.
+ * @param window The widow to activate.
+ * @param name   The title name of the window.
+ *
+ * Set the icon name of @p window to @p name by sending the
+ * _NET_WM_VISIBLE_ICON_NAME property to @p window, when the Window Manager
+ * displays a icon name other than by calling
+ * ecore_x_netwm_icon_name_set().
+ *
+ * The Client SHOULD set the icon name in UTF-8
+ * encoding. The Window Manager MUST use this function is it display
+ * an icon name other than with ecore_x_netwm_icon_name_set().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_icon_name_set(Ecore_X_Window window,
+                                    const char    *name)
+{
+   _ecore_x_window_prop_string_utf8_set(window,
+                                        ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
+                                        name);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_icon_name_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_icon_name_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_visible_icon_name_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the visible icon name of a window.
+ * @param window The window.
+ * @param name   The icon name.
+ * @return       Returns always 1.
+ *
+ * Retrieve the visible icon name of @p window and store it in
+ * @p name. The function returns always 1.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_visible_icon_name_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_visible_icon_name_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_visible_icon_name_get(Ecore_X_Window window,
+                                    char         **name)
+{
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(window,
+                                                  ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_DESKTOP property.
+ * @param window The window.
+ * @param desk   The desktop index.
+ *
+ * Set on which desktop the @p window is in by sending the
+ * _NET_WM_DESKTOP property to @p window. @p desk is the index of
+ * the desktop, starting from 0. To indicate that the window should
+ * appear on all desktops, @p desk must be equal to 0xFFFFFFFF.
+ *
+ * A Client MAY choose not to set this property, in which case the
+ * Window Manager SHOULD place it as it wishes.
+ *
+ * The Window Manager should honor _NET_WM_DESKTOP whenever a
+ * withdrawn window requests to be mapped.
+ *
+ * A Client can request a change of desktop for a non-withdrawn window
+ * by sending a _NET_WM_DESKTOP client message to the root window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desktop_set(Ecore_X_Window window,
+                          unsigned int   desk)
+{
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desktop_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_DESKTOP, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_desktop_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desktop_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the visible icon name of a window.
+ * @param window The window.
+ * @param desk   The desktop index.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the desktop index in which @p window is displayed and
+ * store it in @p desk. If @p desk value is 0xFFFFFFFF, the window
+ * appears on all desktops. The function returns 1 on success, 0
+ * otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_desktop_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_desktop_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_desktop_get(Ecore_X_Window window,
+                          unsigned int *desk)
+{
+   int      ret;
+   uint32_t tmp;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_DESKTOP,
+                                       &tmp, 1);
+
+   if (desk) *desk = tmp;
+   return (ret == 1) ? 1 : 0;
+}
+
+/**
+ * Set the _NET_WM_STRUT property.
+ * @param window The window
+ * @param left   The number of pixels at the left of the screen.
+ * @param right  The number of pixels at the right of the screen.
+ * @param top    The number of pixels at the top of the screen.
+ * @param bottom The number of pixels at the bottom of the screen.
+ *
+ * Set space at the edje of the screen by sending the _NET_WM_STRUT
+ * property to @p window if @p window is to reserve that space.
+ * @p left, @p right, @p top and @p bottom are respectively the number
+ * of pixels at the left, right, top and bottom of the screen.
+ *
+ * This property is deprecated and ecore_x_netwm_strut_partial_set()
+ * should be used instead. However, Clients MAY set this property in
+ * addition to _NET_WM_STRUT_PARTIAL to ensure backward compatibility
+ * with Window Managers supporting older versions of the
+ * Specification.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_set(Ecore_X_Window window,
+                        int            left,
+                        int            right,
+                        int            top,
+                        int            bottom)
+{
+   uint32_t strut[4];
+
+   strut[0] = left;
+   strut[1] = right;
+   strut[2] = top;
+   strut[3] = bottom;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_STRUT, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_strut_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * _NET_WM_STRUT is deprecated
+ */
+
+/**
+ * Get the space at the edje of the screen.
+ * @param window The window
+ * @param left   The number of pixels at the left of the screen.
+ * @param right  The number of pixels at the right of the screen.
+ * @param top    The number of pixels at the top of the screen.
+ * @param bottom The number of pixels at the bottom of the screen.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the space at the edje of the screen if @p window is to
+ * reserve such space. The number of pixels at the left, right, top
+ * and bottom of the screen are respectively stored in @p left,
+ * @p right, @p top and @p bottom. This function returns 1 on success,
+ * 0 otherwise.
+ *
+ * This property is deprecated. See ecore_x_netwm_strut_set() for more
+ * informations.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_strut_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_strut_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_strut_get(Ecore_X_Window window,
+                        int           *left,
+                        int           *right,
+                        int           *top,
+                        int           *bottom)
+{
+   uint32_t strut[4];
+   int      ret = 0;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
+   if (ret != 4)
+     return 0;
+
+   if (left)   *left   = strut[0];
+   if (right)  *right  = strut[1];
+   if (top)    *top    = strut[2];
+   if (bottom) *bottom = strut[3];
+
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_STRUT_PARTIAL property.
+ * @param window         The window
+ * @param left           The number of pixels at the left of the screen.
+ * @param right          The number of pixels at the right of the screen.
+ * @param top            The number of pixels at the top of the screen.
+ * @param bottom         The number of pixels at the bottom of the screen.
+ * @param left_start_y   The number of pixels.
+ * @param left_end_y     The number of pixels.
+ * @param right_start_y  The number of pixels.
+ * @param right_end_y    The number of pixels.
+ * @param top_start_x    The number of pixels.
+ * @param top_end_x      The number of pixels.
+ * @param bottom_start_x The number of pixels.
+ * @param bottom_end_x   The number of pixels.
+ *
+ * Set space at the edje of the screen by sending the
+ * _NET_WM_STRUT_PARTIAL property to @p window if @p window is to
+ * reserve that space. @p left, @p right, @p top and @p bottom are
+ * respectively the number of pixels at the left, right, top and
+ * bottom of the screen.
+ *
+ * TODO: more description for that function.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_partial_set(Ecore_X_Window window,
+                                int            left,
+                                int            right,
+                                int            top,
+                                int            bottom,
+                                int            left_start_y,
+                                int            left_end_y,
+                                int            right_start_y,
+                                int            right_end_y,
+                                int            top_start_x,
+                                int            top_end_x,
+                                int            bottom_start_x,
+                                int            bottom_end_x)
+{
+   unsigned int strut[12];
+
+   strut[0] = left;
+   strut[1] = right;
+   strut[2] = top;
+   strut[3] = bottom;
+   strut[4] = left_start_y;
+   strut[5] = left_end_y;
+   strut[6] = right_start_y;
+   strut[7] = right_end_y;
+   strut[8] = top_start_x;
+   strut[9] = top_end_x;
+   strut[10] = bottom_start_x;
+   strut[11] = bottom_end_x;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_partial_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_strut_partial_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_strut_partial_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the space at the edje of the screen of a window.
+ * @param window         The window
+ * @param left           The number of pixels at the left of the screen.
+ * @param right          The number of pixels at the right of the screen.
+ * @param top            The number of pixels at the top of the screen.
+ * @param bottom         The number of pixels at the bottom of the screen.
+ * @param left_start_y   The number of pixels.
+ * @param left_end_y     The number of pixels.
+ * @param right_start_y  The number of pixels.
+ * @param right_end_y    The number of pixels.
+ * @param top_start_x    The number of pixels.
+ * @param top_end_x      The number of pixels.
+ * @param bottom_start_x The number of pixels.
+ * @param bottom_end_x   The number of pixels.
+ *
+ * Retrieve the space at the edje of the screen if @p window is to
+ * reserve such space. The number of pixels at the left, right, top
+ * and bottom of the screen are respectively stored in @p left,
+ * @p right, @p top and @p bottom. This function returns 1 on success,
+ * 0 otherwise.
+ *
+ * TODO: more description for that function.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_strut_partial_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_strut_partial_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_strut_partial_get(Ecore_X_Window window,
+                                int           *left,
+                                int           *right,
+                                int           *top,
+                                int           *bottom,
+                                int           *left_start_y,
+                                int           *left_end_y,
+                                int           *right_start_y,
+                                int           *right_end_y,
+                                int           *top_start_x,
+                                int           *top_end_x,
+                                int           *bottom_start_x,
+                                int           *bottom_end_x)
+{
+   uint32_t strut[12];
+   int      ret = 0;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
+   if (ret != 12)
+     return 0;
+
+   if (left)           *left           = strut[0];
+   if (right)          *right          = strut[1];
+   if (top)            *top            = strut[2];
+   if (bottom)         *bottom         = strut[3];
+   if (left_start_y)   *left_start_y   = strut[4];
+   if (left_end_y)     *left_end_y     = strut[5];
+   if (right_start_y)  *right_start_y  = strut[6];
+   if (right_end_y)    *right_end_y    = strut[7];
+   if (top_start_x)    *top_start_x    = strut[8];
+   if (top_end_x)      *top_end_x      = strut[9];
+   if (bottom_start_x) *bottom_start_x = strut[10];
+   if (bottom_end_x)   *bottom_end_x   = strut[11];
+   return 1;
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icons_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_ICON, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_icons_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icons_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieve hte possible icons of a window.
+ * @param window The window
+ * @param icon   An array of icons.
+ * @param num    The number of icons.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve an array of possible icons of @p window. The icons are
+ * stored in @p icon and their number in @p num.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_icons_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_icons_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_icons_get(Ecore_X_Window window,
+                        Ecore_X_Icon **icon,
+                        int           *num)
+{
+   uint32_t *data;
+   uint32_t *p;
+   uint32_t *src;
+   uint32_t  icons;
+   uint32_t  len;
+   uint32_t  i;
+   int       num_ret;
+
+   if (num) *num = 0UL;
+   if (icon) *icon = NULL;
+
+   num_ret = ecore_x_window_prop_card32_list_get(window,
+                                                 ECORE_X_ATOM_NET_WM_ICON,
+                                                 &data);
+   if ((num_ret <= 0) || !data)
+     return 0;
+
+   if (num_ret < 2)
+     {
+       free(data);
+       return 0;
+     }
+
+   /* Check how many icons there are */
+   icons = 0;
+   p = data;
+   while (p)
+     {
+       len = p[0] * p[1];
+       p += (len + 2);
+       if ((p - data) > num_ret)
+         {
+            free(data);
+            return 0;
+         }
+       icons++;
+
+       if ((p - data) == num_ret)
+         p = NULL;
+     }
+   if (num) *num = icons;
+
+   /* If the user doesn't want the icons, return */
+   if (!icon)
+     {
+       free(data);
+       return 1;
+     }
+
+   /* Allocate memory */
+   *icon = malloc(icons * sizeof(Ecore_X_Icon));
+   if (!(*icon))
+     {
+       free(data);
+       return 0;
+     }
+
+   /* Fetch the icons */
+   p = data;
+   for (i = 0; i < icons; i++)
+     {
+       uint32_t *ps, *pd, *pe;
+
+       len = p[0] * p[1];
+       ((*icon)[i]).width = p[0];
+       ((*icon)[i]).height = p[1];
+       src = &(p[2]);
+       ((*icon)[i]).data = malloc(len * sizeof(uint32_t));
+       if (!((*icon)[i]).data)
+         {
+            while (i)
+              free(((*icon)[--i]).data);
+            free(*icon);
+            free(data);
+            return 0;
+         }
+
+       pd = ((*icon)[i]).data;
+       ps = src;
+       pe = ps + len;
+       for (; ps < pe; ps++)
+         {
+            uint32_t r, g, b, a;
+
+            a = (*ps >> 24) & 0xff;
+            r = (((*ps >> 16) & 0xff) * a) / 255;
+            g = (((*ps >>  8) & 0xff) * a) / 255;
+            b = (((*ps      ) & 0xff) * a) / 255;
+            *pd = (a << 24) | (r << 16) | (g << 8) | (b);
+            pd++;
+         }
+       p += (len + 2);
+     }
+
+   free(data);
+
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_ICON_GEOMETRY property.
+ * @param window The window.
+ * @param x      The X coordinate of the icon.
+ * @param y      The Y coordinate of the icon.
+ * @param width  The width of the icon.
+ * @param height The height of the icon.
+ *
+ * Set the geometry of the icon of @p window by sending the
+ * _NET_WM_ICON_GEOMETRY property to @p window. @p x, @p y, @p width
+ * and @p height specify respectively the X coordinate, the Y
+ * coordinate, the width and the height of the icon.
+ *
+ * Stand alone tools like a taskbar or an iconbox MAY use this
+ * function. This functions makes possible for a Window Manager to
+ * display a nice animation like morphing the window into its icon.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_geometry_set(Ecore_X_Window window,
+                                int            x,
+                                int            y,
+                                int            width,
+                                int            height)
+{
+   uint32_t geometry[4];
+
+   geometry[0] = (uint32_t)x;
+   geometry[1] = (uint32_t)y;
+   geometry[2] = (uint32_t)width;
+   geometry[3] = (uint32_t)height;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_geometry_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_icon_geometry_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_icon_geometry_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the geometry of an icon.
+ * @param window The window
+ * @param x      x
+ * @param x      The X coordinate of the icon.
+ * @param y      The Y coordinate of the icon.
+ * @param width  The width of the icon.
+ * @param height The height of the icon.
+ * @return       1 on success, 0 othrwise.
+ *
+ * Retrieve the geometry of the icon of @p window. The geometry is
+ * stored in @p x, @p y, @p width and @p height. The function returns
+ * 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_icon_geometry_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_icon_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_icon_geometry_get(Ecore_X_Window window,
+                                int           *x,
+                                int           *y,
+                                int           *width,
+                                int           *height)
+{
+   uint32_t geometry[4];
+   int      ret;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
+   if (ret != 4)
+     return 0;
+
+   if (x)      *x      = geometry[0];
+   if (y)      *y      = geometry[1];
+   if (width)  *width  = geometry[2];
+   if (height) *height = geometry[3];
+
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_PID property.
+ * @param window The window.
+ * @param pid    The process ID.
+ *
+ * Set the process ID of the client owning @p window by sending the
+ * _NET_WM_PID property to @p window.
+ *
+ * This function MAY be used by the Window Manager to kill windows
+ * which do not respond to the _NET_WM_PING protocol.
+ *
+ * If _NET_WM_PID is set, the ICCCM-specified property
+ * WM_CLIENT_MACHINE MUST also be set.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_pid_set(Ecore_X_Window window,
+                      int            pid)
+{
+   unsigned int tmp;
+
+   tmp = pid;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_PID,
+                                 &tmp, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_pid_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_PID, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_pid_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_pid_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the process ID of a client window.
+ * @param window The window.
+ * @param pid    The process ID.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the process ID of @p window and store it in @p pid. This
+ * function returns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_pid_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_pid_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_pid_get(Ecore_X_Window window,
+                      int           *pid)
+{
+   int ret;
+   uint32_t tmp;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_PID,
+                                       &tmp, 1);
+   if (pid) *pid = tmp;
+
+   return (ret == 1) ? 1 : 0;
+}
+
+/**
+ * Set the _NET_WM_HANDLED_ICONS property.
+ * @param window The window.
+ *
+ * Indicate to the Window Manager that it does not need to provide
+ * icons for the iconified @p window by sending the
+ * _NET_WM_HANDLED_ICONS property to @p window.
+ *
+ * This function can be used by a Pager on one of its own toplevel
+ * windows (for example if the Client is a taskbar and provides
+ * buttons for iconified windows).
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_handled_icons_set(Ecore_X_Window window)
+{
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
+                                 NULL, 0);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_handled_icons_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_HANDLED_ICONS, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_handled_icons_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_handled_icons_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Return wheter the Client handles icons or not.
+ * @param window The window.
+ * @return       1 if icons are handled, 0 otherwise.
+ *
+ * Return whether the client handles icons or not if @p window is
+ * iconified.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_handled_icons_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_handled_icons_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_handled_icons_get(Ecore_X_Window window)
+{
+   int ret = 0;
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
+                                       NULL, 0);
+   return (ret == 0) ? 1 : 0;
+}
+
+/**
+ * Set the _NET_WM_USER_TIME property.
+ * @param window The window.
+ * @param time   The last user activity time in the window.
+ *
+ * Set the XServer time at which last user activity in @p window took
+ * place by sending the _NET_WM_USER_TIME property to @p window. @p
+ * time contains that XServer time in seconds.
+ *
+ * This function allows a Window Manager to alter the focus, stacking,
+ * and/or placement behavior of windows when they are mapped depending
+ * on whether the new window was created by a user action or is a
+ * "pop-up" window activated by a timer or some other event.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_user_time_set(Ecore_X_Window window,
+                            unsigned int   time)
+{
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_USER_TIME,
+                                 &time, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_user_time_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_USER_TIME, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_user_time_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_user_time_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the last user activity time in the window.
+ * @param window The window.
+ * @param time   The returned time.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Return the XServer time at which last user activity in @p window
+ * took place. The time is stored in @p time.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_user_time_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_user_time_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_user_time_get(Ecore_X_Window window,
+                            unsigned int  *time)
+{
+   int ret;
+   uint32_t tmp;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_USER_TIME,
+                                       &tmp, 1);
+   if (time) *time = tmp;
+   return (ret == 1) ? 1 : 0;
+}
+
+Ecore_X_Window_State
+_ecore_x_netwm_state_get(Ecore_X_Atom a)
+{
+   if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
+     return ECORE_X_WINDOW_STATE_MODAL;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
+     return ECORE_X_WINDOW_STATE_STICKY;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
+     return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
+     return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
+     return ECORE_X_WINDOW_STATE_SHADED;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
+     return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
+     return ECORE_X_WINDOW_STATE_SKIP_PAGER;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
+     return ECORE_X_WINDOW_STATE_HIDDEN;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
+     return ECORE_X_WINDOW_STATE_FULLSCREEN;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
+     return ECORE_X_WINDOW_STATE_ABOVE;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
+     return ECORE_X_WINDOW_STATE_BELOW;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
+     return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
+   else
+     return ECORE_X_WINDOW_STATE_UNKNOWN;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
+{
+   switch(s)
+     {
+      case ECORE_X_WINDOW_STATE_MODAL:
+        return ECORE_X_ATOM_NET_WM_STATE_MODAL;
+      case ECORE_X_WINDOW_STATE_STICKY:
+        return ECORE_X_ATOM_NET_WM_STATE_STICKY;
+      case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
+        return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
+      case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
+        return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
+      case ECORE_X_WINDOW_STATE_SHADED:
+        return ECORE_X_ATOM_NET_WM_STATE_SHADED;
+      case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
+        return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
+      case ECORE_X_WINDOW_STATE_SKIP_PAGER:
+        return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
+      case ECORE_X_WINDOW_STATE_HIDDEN:
+        return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
+      case ECORE_X_WINDOW_STATE_FULLSCREEN:
+        return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
+      case ECORE_X_WINDOW_STATE_ABOVE:
+        return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
+      case ECORE_X_WINDOW_STATE_BELOW:
+        return ECORE_X_ATOM_NET_WM_STATE_BELOW;
+      case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
+        return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
+      default:
+        return 0;
+     }
+}
+
+/**
+ * Set the _NET_WM_STATE property.
+ * @param window The window.
+ * @param state  An array of window hints.
+ * @param num    The number of hints.
+ *
+ * Set a list of hints describing @p window state by sending the
+ * _NET_WM_STATE property to @p window. The hints are stored in the
+ * array @p state. @p num must contain the number of hints.
+ *
+ * The Window Manager SHOULD honor _NET_WM_STATE whenever a withdrawn
+ * window requests to be mapped. A Client wishing to change the state
+ * of a window MUST send a _NET_WM_STATE client message to the root
+ * window. The Window Manager MUST keep this property updated to
+ * reflect the current state of the window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_state_set(Ecore_X_Window        window,
+                               Ecore_X_Window_State *state,
+                               unsigned int          num)
+{
+   Ecore_X_Atom  *set;
+   uint32_t       i;
+
+   if (!num)
+     {
+       ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_STATE);
+       return;
+     }
+
+   set = malloc(num * sizeof(Ecore_X_Atom));
+   if (!set) return;
+
+   for (i = 0; i < num; i++)
+     set[i] = _ecore_x_netwm_state_atom_get(state[i]);
+
+   ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_STATE, set, num);
+
+   free(set);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_state_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_STATE, ECORE_X_ATOM_ATOM,
+                                       0, 0x7fffffff);;
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_state_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_state_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the hints describing the window state.
+ * @param window The window.
+ * @param state  The returned hins.
+ * @param num    The number of hints.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the hints describing @p window state. The state is
+ * returned in @p state. The nummber of hints is stored in @p
+ * num. This function returns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_window_state_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_window_state_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_window_state_get(Ecore_X_Window         window,
+                               Ecore_X_Window_State **state,
+                               unsigned int          *num)
+{
+   Ecore_X_Atom *atoms;
+   int           num_ret;
+   int           i;
+
+   if (num) *num = 0;
+   if (state) *state = NULL;
+
+   num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_STATE,
+                                              &atoms);
+   if (num_ret <= 0)
+      return 0;
+
+   if (state)
+     {
+       *state = malloc(num_ret * sizeof(Ecore_X_Window_State));
+       if (*state)
+         for (i = 0; i < num_ret; ++i)
+           (*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
+
+       if (num) *num = num_ret;
+     }
+
+   free(atoms);
+
+   return 1;
+}
+
+static Ecore_X_Window_Type
+_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
+{
+   if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
+     return ECORE_X_WINDOW_TYPE_DESKTOP;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
+     return ECORE_X_WINDOW_TYPE_DOCK;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
+     return ECORE_X_WINDOW_TYPE_TOOLBAR;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
+     return ECORE_X_WINDOW_TYPE_MENU;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
+     return ECORE_X_WINDOW_TYPE_UTILITY;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
+     return ECORE_X_WINDOW_TYPE_SPLASH;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
+     return ECORE_X_WINDOW_TYPE_DIALOG;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
+     return ECORE_X_WINDOW_TYPE_NORMAL;
+   else
+     return ECORE_X_WINDOW_TYPE_UNKNOWN;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
+{
+   switch (type)
+     {
+      case ECORE_X_WINDOW_TYPE_DESKTOP:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
+      case ECORE_X_WINDOW_TYPE_DOCK:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
+      case ECORE_X_WINDOW_TYPE_TOOLBAR:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
+      case ECORE_X_WINDOW_TYPE_MENU:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
+      case ECORE_X_WINDOW_TYPE_UTILITY:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
+      case ECORE_X_WINDOW_TYPE_SPLASH:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
+      case ECORE_X_WINDOW_TYPE_DIALOG:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
+      case ECORE_X_WINDOW_TYPE_NORMAL:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
+      default:
+        return 0;
+     }
+}
+
+/*
+ * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
+ * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
+ */
+
+/**
+ * Set the _NET_WM_WINDOW_TYPE property.
+ * @param window The window.
+ * @param type   The functional type of the window.
+ *
+ * Set the functional @p type of @p window by sending _NET_WM_WINDOW_TYPE
+ * property to @p window.
+ *
+ * This property SHOULD be set by the Client before mapping. This
+ * property SHOULD be used by the window manager in determining the
+ * decoration, stacking position and other behavior of the window. The
+ * Client SHOULD specify window types in order of preference (the first
+ * being most preferable).
+ *
+ * This hint is intended to replace the MOTIF hints.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_type_set(Ecore_X_Window      window,
+                              Ecore_X_Window_Type type)
+{
+   Ecore_X_Atom atom;
+
+   atom = _ecore_x_netwm_window_type_atom_get(type);
+   ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                               &atom, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_type_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_WINDOW_TYPE, ECORE_X_ATOM_ATOM,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_type_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_window_type_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/* FIXME: Maybe return 0 on some conditions? */
+
+/**
+ * Get the functional type of a window.
+ * @param window The window.
+ * @param type   The function type of the window.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the functional type of @p window. The type is stored in
+ * @p type. This function returns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_window_type_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_window_type_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_window_type_get(Ecore_X_Window       window,
+                              Ecore_X_Window_Type *type)
+{
+   Ecore_X_Atom *atoms;
+   int           num;
+   int           i;
+
+   if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL;
+
+   num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                                          &atoms);
+   if (num < 0)
+     {
+       /* IMO this is not the place to mix netwm and icccm /kwo */
+       /* Check if WM_TRANSIENT_FOR is set */
+
+        /* Disable it for xcb */
+
+/*     if ((type) && (ecore_x_icccm_transient_for_get(window))) */
+/*       *type = ECORE_X_WINDOW_TYPE_DIALOG; */
+/*     return 1; */
+     }
+
+   if (type)
+     {
+       for (i = 0; i < num; ++i)
+         {
+            *type = _ecore_x_netwm_window_type_type_get(atoms[i]);
+            if (*type != ECORE_X_WINDOW_TYPE_UNKNOWN)
+              break;
+         }
+     }
+
+   free(atoms);
+
+   return 1;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_action_atom_get(Ecore_X_Action action)
+{
+   switch (action)
+     {
+      case ECORE_X_ACTION_MOVE:
+        return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
+      case ECORE_X_ACTION_RESIZE:
+        return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
+      case ECORE_X_ACTION_MINIMIZE:
+        return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
+      case ECORE_X_ACTION_SHADE:
+        return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
+      case ECORE_X_ACTION_STICK:
+        return ECORE_X_ATOM_NET_WM_ACTION_STICK;
+      case ECORE_X_ACTION_MAXIMIZE_HORZ:
+        return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
+      case ECORE_X_ACTION_MAXIMIZE_VERT:
+        return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
+      case ECORE_X_ACTION_FULLSCREEN:
+        return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
+      case ECORE_X_ACTION_CHANGE_DESKTOP:
+        return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
+      case ECORE_X_ACTION_CLOSE:
+        return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
+      case ECORE_X_ACTION_ABOVE:
+        return ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
+      case ECORE_X_ACTION_BELOW:
+        return ECORE_X_ATOM_NET_WM_ACTION_BELOW;
+      default:
+        return 0;
+     }
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_allowed_action_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, ECORE_X_ATOM_ATOM,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_allowed_action_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_allowed_action_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/* FIXME: Get complete list */
+
+/**
+ * Check whether an action is supported by a window.
+ * @param window The window
+ * @param action The action
+ * @return       1 if set, 0 otherwise.
+ *
+ * Return whether the user operation @p action is supported by the
+ * Window Manager for @p window.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_allowed_action_isset(Ecore_X_Window window,
+                                   Ecore_X_Action action)
+{
+   Ecore_X_Atom *atoms;
+   Ecore_X_Atom  atom;
+   int           num;
+   int           ret = 0;
+   int           i;
+
+   num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
+                                          &atoms);
+   if (num <= 0)
+     return ret;
+
+   atom = _ecore_x_netwm_action_atom_get(action);
+
+   for (i = 0; i < num; ++i)
+     {
+       if (atom == atoms[i])
+         {
+            ret = 1;
+            break;
+         }
+     }
+
+   free(atoms);
+
+   return ret;
+}
+
+/* FIXME: Set complete list */
+/**
+ * Set the _NET_WM_ALLOWED_ACTIONS property.
+ * @param window The window.
+ * @param action An array of allowed actions.
+ * @param num    The number of actions.
+ *
+ * Set the user operations that the Window Manager supports for
+ * @p window by sending the _NET_WM_ALLOWED_ACTIONS property to
+ * @p window. @p action stores @p num actions.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_allowed_action_set(Ecore_X_Window  window,
+                                 Ecore_X_Action *action,
+                                 unsigned int    num)
+{
+   Ecore_X_Atom  *set;
+   unsigned int   i;
+
+   if (!num)
+     {
+       ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
+       return;
+     }
+
+   set = malloc(num * sizeof(Ecore_X_Atom));
+   if (!set) return;
+
+   for (i = 0; i < num; i++)
+     set[i] = _ecore_x_netwm_action_atom_get(action[i]);
+
+   ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, set, num);
+
+   free(set);
+}
+
+/**
+ * Get the allowed actions supported by a window.
+ * @param window The window.
+ * @param action The returned array of the actions.
+ * @param num    The number of actions.
+ * @return       1 on success, 0 otherwise.
+ *
+ * Retrieve the user operations that the Window Manager supports for
+ * @p window and store them in @p action. The number of actions is
+ * stored in @p num. This function returns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_allowed_action_get(Ecore_X_Window   window,
+                                 Ecore_X_Action **action,
+                                 unsigned int    *num)
+{
+   Ecore_X_Atom *atoms;
+   int           num_ret;
+   int           i;
+
+   if (num) *num = 0;
+   if (action) *action = NULL;
+
+   num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
+                                              &atoms);
+   if (num_ret <= 0)
+      return 0;
+
+   if (action)
+     {
+       *action = malloc(num_ret * sizeof(Ecore_X_Action));
+       if (*action)
+         for (i = 0; i < num_ret; ++i)
+           (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
+
+       if (num) *num = num_ret;
+     }
+
+   free(atoms);
+
+   return 1;
+}
+
+/**
+ * Set the _NET_WM_WINDOW_OPACITY property.
+ * @param window  The window.
+ * @param opacity The opacity value.
+ *
+ * Set the desired opacity of @p window by sending the
+ * _NET_WM_WINDOW_OPACITY property to @p window. @p opacity is 0 for a
+ * transparent window and 0xffffffff for an opaque window. @p opacity
+ * must be multiplied with the original alpha value of @p window
+ * (which is 1 for visuals not including an alpha component) so that
+ * @p window content is modulated by the opacity value.
+ *
+ * Window Managers acting as compositing managers MAY take this into
+ * account when displaying a window. Window Managers MUST forward the
+ * value of this property to any enclosing frame window.  This
+ * property MAY change while the window is mapped and the Window
+ * Manager MUST respect changes while the window is mapped.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_opacity_set(Ecore_X_Window window,
+                          unsigned int   opacity)
+{
+   uint32_t op = opacity;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
+                                 &op, 1);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_opacity_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_opacity_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_opacity_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the opacity value of a window.
+ * @param window  The window.
+ * @param opacity The returned opacity.
+ * @return        1 on success, 0 otherwise.
+ *
+ * Retriee the opacity value of @p window and store it in
+ * @p opacity. This function returns 1 on sucess, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_opacity_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_opacity_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_opacity_get(Ecore_X_Window window,
+                          unsigned int  *opacity)
+{
+   int ret;
+   unsigned int tmp;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
+                                       &tmp, 1);
+   if (opacity) *opacity = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+/**
+ * Set the _NET_FRAME_EXTENTS property.
+ * @param window The window.
+ * @param fl     The number of pixels of the left border of the window.
+ * @param fr     The number of pixels of the right border of the window.
+ * @param ft     The number of pixels of the top border of the window.
+ * @param fb     The number of pixels of the bottom border of the window.
+ *
+ * Set the border witdh of @p window by sending the _NET_FRAME_EXTENTS
+ * property to @p window. @p fl, @p fr, @p ft and @p fb are respectively
+ * the number of pixels of the left, right, top and bottom border of
+ * @p window.
+ *
+ * The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of
+ * the window's frame.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_frame_size_set(Ecore_X_Window window,
+                             int            fl,
+                             int            fr,
+                             int            ft,
+                             int            fb)
+{
+   uint32_t frames[4];
+
+   frames[0] = fl;
+   frames[1] = fr;
+   frames[2] = ft;
+   frames[3] = fb;
+   ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_frame_size_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_FRAME_EXTENTS, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_frame_size_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_frame_size_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the frame extent of a window.
+ * @param window  The window.
+ * @param fl      The number of pixels of the left border of the window.
+ * @param fr      The number of pixels of the right border of the window.
+ * @param ft      The number of pixels of the top border of the window.
+ * @param fb      The number of pixels of the bottom border of the window.
+ * @return        1 on success, 0 otherwise.
+ *
+ * Retrieve the frame extents of @p window. The number of pixels of
+ * the left, right, top and bottom border of @p window are
+ * respectively stored in @p fl, @p fr, @p ft anfd @p fb. TYhis
+ * function retuirns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_frame_size_get(Ecore_X_Window window,
+                             int           *fl,
+                             int           *fr,
+                             int           *ft,
+                             int           *fb)
+{
+   uint32_t frames[4];
+   int      ret = 0;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
+   if (ret != 4)
+     return 0;
+
+   if (fl) *fl = frames[0];
+   if (fr) *fr = frames[1];
+   if (ft) *ft = frames[2];
+   if (fb) *fb = frames[3];
+   return 1;
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window The window.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_sync_counter_get_prefetch(Ecore_X_Window window)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_netwm_sync_counter_get_prefetch().
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_sync_counter_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get the X ID of a X Sync counter.
+ * @param window  The window.
+ * @param counter The X ID of the Sync counter.
+ * @return        1 on success, 0 otherwise.
+ *
+ * Retrieve the X ID of the X Sync counter of @p window and store it
+ * in @p counter. This function returns 1 on success, 0 otherwise.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_netwm_sync_counter_get(Ecore_X_Window        window,
+                               Ecore_X_Sync_Counter *counter)
+{
+   int          ret;
+   unsigned int tmp;
+
+   ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
+                                       &tmp, 1);
+
+   if (counter) *counter = tmp;
+   return (ret == 1) ? 1 : 0;
+}
+
+/**
+ * Send a _NET_WM_PING property event.
+ * @param window The window.
+ *
+ * Send a ClientMessage event from @p window with the _NET_WM_PING
+ * property set.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_ping_send(Ecore_X_Window window)
+{
+   xcb_client_message_event_t ev;
+
+   if (!window) return;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.sequence = 0;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
+   ev.data.data32[0] = ECORE_X_ATOM_NET_WM_PING;
+   ev.data.data32[1] = _ecore_xcb_event_last_time;
+   ev.data.data32[2] = window;
+   ev.data.data32[3] = 0;
+   ev.data.data32[4] = 0;
+   ev.data.data32[5] = 0;
+
+   xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
+}
+
+/**
+ * Send a _NET_WM_SYNC_REQUEST property event.
+ * @param window The window.
+ * @param serial The update request number.
+ *
+ * Send a ClientMessage event from @p window with the _NET_WM_SYNC_REQUEST
+ * property set.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_sync_request_send(Ecore_X_Window window,
+                                unsigned int   serial)
+{
+   xcb_client_message_event_t ev;
+
+   if (!window) return;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
+   ev.data.data32[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
+   ev.data.data32[1] = _ecore_xcb_event_last_time;
+   ev.data.data32[2] = serial;
+   /* FIXME: imho, the following test is useless as serial is non negative */
+   /* should we remove it ? */
+   ev.data.data32[3] = (serial < 0) ? ~0L : 0L;
+   ev.data.data32[4] = 0;
+
+   xcb_send_event(_ecore_xcb_conn, 0, window, 0, (const char *)&ev);
+}
+
+/**
+ * Send a _NET_WM_STATE property event.
+ * @param window The window.
+ * @param root   The root window.
+ * @param s1     The first state to alter.
+ * @param s2     The second state to alter.
+ * @param set    0 to unset the property, set it otherwise.
+ *
+ * Send a ClientMessage event from @p window to the @p root window
+ * with the _NET_WM_STATE property set. This change the state of a
+ * mapped window. @p s1 is the first state to alter. @p s2 is the
+ * second state to alter. If @p set value is 0, the property is
+ * removed (or unset), otherwise, the property is set.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_state_request_send(Ecore_X_Window       window,
+                                 Ecore_X_Window       root,
+                                 Ecore_X_Window_State s1,
+                                 Ecore_X_Window_State s2,
+                                 int                  set)
+{
+   xcb_client_message_event_t ev;
+
+   if (!window) return;
+   if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_NET_WM_STATE;
+   ev.data.data32[0] = !!set;
+   ev.data.data32[1] = _ecore_x_netwm_state_atom_get(s1);
+   ev.data.data32[2] = _ecore_x_netwm_state_atom_get(s2);
+   /* 1 == normal client, if someone wants to use this
+    * function in a pager, this should be 2 */
+   ev.data.data32[3] = 1;
+   ev.data.data32[4] = 0;
+
+   xcb_send_event(_ecore_xcb_conn, 0, root,
+                  XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+                  (const char *)&ev);
+}
+
+/**
+ * Send a _NET_WM_DESKTOP property event.
+ * @param window  The window.
+ * @param root    The root window.
+ * @param desktop The new desktop index.
+ *
+ * Send a ClientMessage event from @p window to the @p root window
+ * with the _NET_WM_DESKTOP property set. This change the state of a
+ * non-withdrawn window. @p desktop is the new desktop index to set.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI void
+ecore_x_netwm_desktop_request_send(Ecore_X_Window window,
+                                   Ecore_X_Window root,
+                                   unsigned int   desktop)
+{
+   xcb_client_message_event_t ev;
+
+   if (!window) return;
+   if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
+   ev.format = 32;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_NET_WM_DESKTOP;
+   ev.data.data32[0] = desktop;
+
+   xcb_send_event(_ecore_xcb_conn, 0, root,
+                  XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+                  (const char *)&ev);
+}
+
+int
+_ecore_x_netwm_startup_info_begin(Ecore_X_Window window,
+                                  char          *data)
+{
+#if 0
+   Ecore_X_Startup_Info *info;
+   unsigned char       exists = 0;
+
+   if (!startup_info) return 0;
+   info = eina_hash_find(startup_info, (void *)window);
+   if (info)
+     {
+        exists = 1;
+       INF("Already got info for win: 0x%x", window);
+       _ecore_x_netwm_startup_info_free(info);
+     }
+   info = calloc(1, sizeof(Ecore_X_Startup_Info));
+   if (!info) return 0;
+   info->win = win;
+   info->length = 0;
+   info->buffer_size = 161;
+   info->buffer = calloc(info->buffer_size, sizeof(char));
+   if (!info->buffer)
+     {
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+   memcpy(info->buffer, data, 20);
+   info->length += 20;
+   info->buffer[info->length] = 0;
+   if (exists)
+     eina_hash_modify(startup_info, (void *)info->win, info);
+   else
+     eina_hash_add(startup_info, (void *)info->win, info);
+   if (strlen(info->buffer) != 20)
+     {
+       /* We have a '\0' in there, the message is done */
+       _ecore_x_netwm_startup_info_process(info);
+     }
+#else
+   window = XCB_NONE;
+   data = NULL;
+#endif
+
+   return 1;
+}
+
+int
+_ecore_x_netwm_startup_info(Ecore_X_Window window,
+                            char          *data)
+{
+#if 0
+   Ecore_X_Startup_Info *info;
+   char *p;
+
+   if (!startup_info) return 0;
+   info = eina_hash_find(startup_info, (void *)window);
+   if (!info) return 0;
+   if ((info->length + 20) > info->buffer_size)
+     {
+       info->buffer_size += 160;
+       info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
+       if (!info->buffer)
+         {
+            eina_hash_del(startup_info, (void *)info->win);
+            _ecore_x_netwm_startup_info_free(info);
+            return 0;
+         }
+     }
+   memcpy(info->buffer + info->length, data, 20);
+   p = info->buffer + info->length;
+   info->length += 20;
+   info->buffer[info->length] = 0;
+   if (strlen(p) != 20)
+     {
+       /* We have a '\0' in there, the message is done */
+       _ecore_x_netwm_startup_info_process(info);
+     }
+#else
+   window = XCB_NONE;
+   data = NULL;
+#endif
+
+   return 1;
+}
+
+/*
+ * Set UTF-8 string property
+ */
+static void
+_ecore_x_window_prop_string_utf8_set(Ecore_X_Window window,
+                                     Ecore_X_Atom   atom,
+                                     const char    *str)
+{
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       atom, ECORE_X_ATOM_UTF8_STRING,
+                       8, strlen(str), str);
+}
+
+static void
+_ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window,
+                                              Ecore_X_Atom atom)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window,
+                                       atom, ECORE_X_ATOM_UTF8_STRING,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Get UTF-8 string property
+ * call _ecore_x_window_prop_string_utf8_get_prefetch() before.
+ */
+static char *
+_ecore_x_window_prop_string_utf8_get(Ecore_X_Window window __UNUSED__,
+                                     Ecore_X_Atom   atom __UNUSED__)
+{
+   xcb_get_property_reply_t *reply;
+   char                     *str;
+   int                       length;
+
+   reply = _ecore_xcb_reply_get((Ecore_Xcb_Reply_Cb)xcb_get_property_reply);
+   if (!reply) return NULL;
+
+   if ((reply->format != 8) ||
+       (reply->value_len <= 0))
+     {
+       free(reply);
+       return NULL;
+     }
+
+   length = reply->value_len;
+   str = (char *)malloc (sizeof (char) * (length + 1));
+   if (!str)
+     {
+        free(reply);
+        return NULL;
+     }
+   memcpy(str, xcb_get_property_value(reply), length);
+   str[length] = '\0';
+
+   free(reply);
+   return str;
+}
+
+#if 0 /* Unused */
+/*
+ * Process startup info
+ */
+static int
+_ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
+{
+   Ecore_X_Event_Startup_Sequence *e;
+   int                             event;
+   char                           *p;
+
+   p = strchr(info->buffer, ':');
+   if (!p)
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+   *p = 0;
+   if (!strcmp(info->buffer, "new"))
+     {
+       if (info->init)
+         event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
+       else
+         event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
+       info->init = 1;
+     }
+   else if (!strcmp(info->buffer, "change"))
+     {
+       event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
+     }
+   else if (!strcmp(info->buffer, "remove"))
+     event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
+   else
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+
+   p++;
+
+   if (!_ecore_x_netwm_startup_info_parse(info, p))
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+
+   if (info->init)
+     {
+       e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
+       if (!e)
+         {
+            eina_hash_del(startup_info, (void *)info->win);
+            _ecore_x_netwm_startup_info_free(info);
+            return 0;
+         }
+       e->win = info->win;
+       ecore_event_add(event, e, NULL, NULL);
+     }
+
+   if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
+     {
+        eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+     }
+   else
+     {
+       /* Discard buffer */
+       info->length = 0;
+       info->buffer[0] = 0;
+     }
+   return 1;
+}
+
+/*
+ * Parse startup info
+ */
+static int
+_ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
+                                  char                 *data)
+{
+
+   while (*data)
+     {
+       int in_quot_sing, in_quot_dbl, escaped;
+       char *p, *pp;
+       char *key;
+       char value[1024];
+
+       /* Skip space */
+       while (*data == ' ') data++;
+       /* Get key */
+       key = data;
+       data = strchr(key, '=');
+       if (!data) return 0;
+       *data = 0;
+       data++;
+
+       /* Get value */
+       p = data;
+       pp = value;
+       in_quot_dbl = 0;
+       in_quot_sing = 0;
+       escaped = 0;
+       while (*p)
+         {
+            if ((pp - value) >= 1024) return 0;
+            if (escaped)
+              {
+                 *pp = *p;
+                 pp++;
+                 escaped = 0;
+              }
+            else if (in_quot_sing)
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\'')
+                   in_quot_sing = 0;
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            else if (in_quot_dbl)
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\"')
+                   in_quot_dbl = 0;
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            else
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\'')
+                   in_quot_sing = 1;
+                 else if (*p == '\"')
+                   in_quot_dbl = 1;
+                 else if (*p == ' ')
+                   {
+                      break;
+                   }
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            p++;
+         }
+       if ((in_quot_dbl) || (in_quot_sing)) return 0;
+       data = p;
+       *pp = 0;
+
+       /* Parse info */
+       if (!strcmp(key, "ID"))
+         {
+            if ((info->id) && (strcmp(info->id, value))) return 0;
+            info->id = strdup(value);
+            p = strstr(value, "_TIME");
+            if (p)
+              {
+                 info->timestamp = atoi(p + 5);
+              }
+         }
+       else if (!strcmp(key, "NAME"))
+         {
+            if (info->name) free(info->name);
+            info->name = strdup(value);
+         }
+       else if (!strcmp(key, "SCREEN"))
+         {
+            info->screen = atoi(value);
+         }
+       else if (!strcmp(key, "BIN"))
+         {
+            if (info->bin) free(info->bin);
+            info->bin = strdup(value);
+         }
+       else if (!strcmp(key, "ICON"))
+         {
+            if (info->icon) free(info->icon);
+            info->icon = strdup(value);
+         }
+       else if (!strcmp(key, "DESKTOP"))
+         {
+            info->desktop = atoi(value);
+         }
+       else if (!strcmp(key, "TIMESTAMP"))
+         {
+            if (!info->timestamp)
+              info->timestamp = atoi(value);
+         }
+       else if (!strcmp(key, "DESCRIPTION"))
+         {
+            if (info->description) free(info->description);
+            info->description = strdup(value);
+         }
+       else if (!strcmp(key, "WMCLASS"))
+         {
+            if (info->wmclass) free(info->wmclass);
+            info->wmclass = strdup(value);
+         }
+       else if (!strcmp(key, "SILENT"))
+         {
+            info->silent = atoi(value);
+         }
+       else
+         {
+            WRN("Ecore X Sequence, Unknown: %s=%s", key, value);
+         }
+     }
+   if (!info->id) return 0;
+   return 1;
+}
+#endif
+
+/*
+ * Free startup info struct
+ */
+static void
+_ecore_x_netwm_startup_info_free(void *data)
+{
+   Ecore_X_Startup_Info *info;
+
+   info = data;
+   if (!info) return;
+   if (info->buffer) free(info->buffer);
+   if (info->id) free(info->id);
+   if (info->name) free(info->name);
+   if (info->bin) free(info->bin);
+   if (info->icon) free(info->icon);
+   if (info->description) free(info->description);
+   if (info->wmclass) free(info->wmclass);
+   free(info);
+}
+
+/*
+ * Is screen composited?
+ */
+
+/* FIXME: one round trip can be removed. Can we keep it ? */
+
+/**
+ * Check whether a screen is composited or not.
+ * @param screen The screen index.
+ *
+ * Return 1 if @p screen is composited, 0 otherwise.
+ * @ingroup Ecore_X_NetWM_Group
+ */
+EAPI int
+ecore_x_screen_is_composited(int screen)
+{
+   char                             buf[32];
+   xcb_intern_atom_cookie_t         cookie_atom;
+   xcb_get_selection_owner_cookie_t cookie_owner;
+   xcb_intern_atom_reply_t         *reply_atom;
+   xcb_get_selection_owner_reply_t *reply_owner;
+   Ecore_X_Window                   window;
+   Ecore_X_Atom                     atom;
+
+   snprintf(buf, sizeof(buf), "_NET_WM_CM_S%d", screen);
+   cookie_atom = xcb_intern_atom_unchecked(_ecore_xcb_conn, 1,
+                                           strlen(buf), buf);
+   reply_atom = xcb_intern_atom_reply(_ecore_xcb_conn, cookie_atom, NULL);
+   if (!reply_atom) return 0;
+   atom = reply_atom->atom;
+   free(reply_atom);
+
+   cookie_owner = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, atom);
+   reply_owner = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie_owner, NULL);
+   if (!reply_owner) return 0;
+
+   window = reply_owner->owner;
+   free(reply_owner);
+
+   return window != XCB_NONE;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c b/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c
new file mode 100644 (file)
index 0000000..11a7675
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Pixmap_Group X Pixmap Functions
+ *
+ * Functions that operate on pixmaps.
+ */
+
+
+/**
+ * Creates a new pixmap.
+ * @param   win Window used to determine which screen of the display the
+ *              pixmap should be created on.  If 0, the default root window
+ *              is used.
+ * @param   w   Width of the new pixmap.
+ * @param   h   Height of the new pixmap.
+ * @param   dep Depth of the pixmap.  If 0, the default depth of the default
+ *              screen is used.
+ * @return  New pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI Ecore_X_Pixmap
+ecore_x_pixmap_new(Ecore_X_Window win,
+                   int            w,
+                   int            h,
+                   int            dep)
+{
+   Ecore_X_Pixmap pmap;
+
+   if (win == 0) win = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+   if (dep == 0) dep = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth;
+
+   pmap = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_pixmap(_ecore_xcb_conn, dep, pmap, win, w, h);
+
+   return pmap;
+}
+
+
+/**
+ * Deletes the reference to the given pixmap.
+ *
+ * If no other clients have a reference to the given pixmap, the server
+ * will destroy it.
+ *
+ * @param   pmap The given pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_free(Ecore_X_Pixmap pmap)
+{
+   xcb_free_pixmap(_ecore_xcb_conn, pmap);
+}
+
+
+/**
+ * Pastes a rectangular area of the given pixmap onto the given drawable.
+ * @param   pmap The given pixmap.
+ * @param   dest The given drawable.
+ * @param   gc   The graphics context which governs which operation will
+ *               be used to paste the area onto the drawable.
+ * @param   sx   The X position of the area on the pixmap.
+ * @param   sy   The Y position of the area on the pixmap.
+ * @param   w    The width of the area.
+ * @param   h    The height of the area.
+ * @param   dx   The X position at which to paste the area on @p dest.
+ * @param   dy   The Y position at which to paste the area on @p dest.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_paste(Ecore_X_Pixmap   pmap,
+                     Ecore_X_Drawable dest,
+                    Ecore_X_GC       gc,
+                     int              sx,
+                     int              sy,
+                    int              w,
+                     int              h,
+                     int              dx,
+                     int              dy)
+{
+   xcb_copy_area(_ecore_xcb_conn, pmap, dest, gc, sx, sy, dx, dy, w, h);
+}
+
+
+/**
+ * Retrieves the size of the given pixmap.
+ * @param   pmap The given pixmap.
+ * @param   x    Pointer to an integer in which to store the X position.
+ * @param   y    Pointer to an integer in which to store the Y position.
+ * @param   w    Pointer to an integer in which to store the width.
+ * @param   h    Pointer to an integer in which to store the height.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h)
+{
+   if (pmap)
+      ecore_x_drawable_geometry_get(pmap, x, y, w, h);
+}
+
+
+/**
+ * Retrieves the depth of the given pixmap.
+ * @param   pmap The given pixmap.
+ * @return  The depth of the pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI int
+ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap)
+{
+   return ecore_x_drawable_depth_get(pmap);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_private.h b/src/lib/ecore_x/xcb/ecore_xcb_private.h
new file mode 100644 (file)
index 0000000..0416ea0
--- /dev/null
@@ -0,0 +1,363 @@
+#ifndef __ECORE_XCB_PRIVATE_H__
+#define __ECORE_XCB_PRIVATE_H__
+
+#include "config.h"
+
+#include <sys/param.h>
+
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
+#ifndef XK_MISCELLANY
+# define XK_MISCELLANY 1
+#endif /* XK_MISCELLANY */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_keysyms.h>
+#include <xcb/bigreq.h>
+#ifdef ECORE_XCB_CURSOR
+# include <xcb/cursor.h>
+#endif /* ECORE_XCB_CURSOR */
+#ifdef ECORE_XCB_DAMAGE
+# include <xcb/damage.h>
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_COMPOSITE
+# include <xcb/composite.h>
+#endif /* ECORE_XCB_COMPOSITE */
+#ifdef ECORE_XCB_DPMS
+# include <xcb/dpms.h>
+#endif /* ECORE_XCB_DPMS */
+#ifdef ECORE_XCB_RANDR
+# include <xcb/randr.h>
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_RENDER
+# include <xcb/render.h>
+#endif /* ECORE_XCB_RENDER */
+#ifdef ECORE_XCB_SCREENSAVER
+# include <xcb/screensaver.h>
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+# include <xcb/shape.h>
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+# include <xcb/sync.h>
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_XFIXES
+# include <xcb/xfixes.h>
+#endif /* ECORE_XCB_XFIXES */
+#ifdef ECORE_XCB_XINERAMA
+# include <xcb/xinerama.h>
+#endif /* ECORE_XCB_XINERAMA */
+#ifdef ECORE_XCB_XPRINT
+# include <xcb/xprint.h>
+#endif /* ECORE_XCB_XPRINT */
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_X.h"
+
+extern int _ecore_x11xcb_log_dom ;
+
+#ifdef ECORE_XLIB_XCB_DEFAULT_LOG_COLOR
+# undef ECORE_XLIB_XCB_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_XLIB_XCB_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_x11xcb_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_x11xcb_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_x11xcb_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_x11xcb_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_x11xcb_log_dom, __VA_ARGS__)
+
+typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern;
+
+struct _Ecore_X_Selection_Intern
+{
+   Ecore_X_Window    win;
+   Ecore_X_Atom      selection;
+   unsigned char     *data;
+   int               length;
+   Ecore_X_Time      time;
+};
+
+typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter;
+
+struct _Ecore_X_Selection_Converter
+{
+   Ecore_X_Atom target;
+   int (*convert)(char *target, void *data, int size,
+                  void **data_ret, int *size_ret);
+   Ecore_X_Selection_Converter *next;
+};
+
+typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser;
+
+struct _Ecore_X_Selection_Parser
+{
+   char     *target;
+   void *(*parse)(const char *target, void *data, int size, int format);
+   Ecore_X_Selection_Parser *next;
+};
+
+typedef struct _Ecore_X_DND_Source
+{
+   int version;
+   Ecore_X_Window win, dest;
+
+   enum {
+      ECORE_X_DND_SOURCE_IDLE,
+      ECORE_X_DND_SOURCE_DRAGGING,
+      ECORE_X_DND_SOURCE_DROPPED,
+      ECORE_X_DND_SOURCE_CONVERTING
+   } state;
+
+   struct {
+      short x, y;
+      unsigned short width, height;
+   } rectangle;
+
+   struct {
+      Ecore_X_Window window;
+      int x, y;
+   } prev;
+   
+   Ecore_X_Time time;
+
+   Ecore_X_Atom action, accepted_action;
+
+   int will_accept;
+   int suppress;
+
+   int await_status;
+} Ecore_X_DND_Source;
+
+typedef struct _Ecore_X_DND_Target
+{
+   int version;
+   Ecore_X_Window win, source;
+
+   enum {
+      ECORE_X_DND_TARGET_IDLE,
+      ECORE_X_DND_TARGET_ENTERED
+   } state;
+
+   struct {
+      int x, y;
+   } pos;
+
+   Ecore_X_Time time;
+
+   Ecore_X_Atom action, accepted_action;
+
+   int will_accept;
+} Ecore_X_DND_Target;
+
+extern int ECORE_X_MODIFIER_SHIFT;
+extern int ECORE_X_MODIFIER_CTRL; 
+extern int ECORE_X_MODIFIER_ALT; 
+extern int ECORE_X_MODIFIER_WIN; 
+extern int ECORE_X_LOCK_SCROLL; 
+extern int ECORE_X_LOCK_NUM; 
+extern int ECORE_X_LOCK_CAPS; 
+
+extern Ecore_X_Connection *_ecore_xcb_conn;
+extern Ecore_X_Screen     *_ecore_xcb_screen;
+extern double              _ecore_xcb_double_click_time;
+extern Ecore_X_Time        _ecore_xcb_event_last_time;
+extern Ecore_X_Window      _ecore_xcb_event_last_window;
+extern int16_t             _ecore_xcb_event_last_root_x;
+extern int16_t             _ecore_xcb_event_last_root_y;
+extern int                 _ecore_xcb_xcursor;
+
+extern Ecore_X_Atom        _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
+
+extern int                 _ecore_window_grabs_num;
+extern Ecore_X_Window     *_ecore_window_grabs;
+extern int               (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event);
+extern void               *_ecore_window_grab_replay_data;
+
+extern Ecore_X_Window      _ecore_xcb_private_window;
+
+
+void _ecore_x_error_handler_init(void);
+
+void _ecore_x_event_handle_any_event          (xcb_generic_event_t *event);
+void _ecore_x_event_handle_key_press          (xcb_generic_event_t *event);
+void _ecore_x_event_handle_key_release        (xcb_generic_event_t *event);
+void _ecore_x_event_handle_button_press       (xcb_generic_event_t *event);
+void _ecore_x_event_handle_button_release     (xcb_generic_event_t *event);
+void _ecore_x_event_handle_motion_notify      (xcb_generic_event_t *event);
+void _ecore_x_event_handle_enter_notify       (xcb_generic_event_t *event);
+void _ecore_x_event_handle_leave_notify       (xcb_generic_event_t *event);
+void _ecore_x_event_handle_focus_in           (xcb_generic_event_t *event);
+void _ecore_x_event_handle_focus_out          (xcb_generic_event_t *event);
+void _ecore_x_event_handle_keymap_notify      (xcb_generic_event_t *event);
+void _ecore_x_event_handle_expose             (xcb_generic_event_t *event);
+void _ecore_x_event_handle_graphics_expose    (xcb_generic_event_t *event);
+void _ecore_x_event_handle_visibility_notify  (xcb_generic_event_t *event);
+void _ecore_x_event_handle_create_notify      (xcb_generic_event_t *event);
+void _ecore_x_event_handle_destroy_notify     (xcb_generic_event_t *event);
+void _ecore_x_event_handle_unmap_notify       (xcb_generic_event_t *event);
+void _ecore_x_event_handle_map_notify         (xcb_generic_event_t *event);
+void _ecore_x_event_handle_map_request        (xcb_generic_event_t *event);
+void _ecore_x_event_handle_reparent_notify    (xcb_generic_event_t *event);
+void _ecore_x_event_handle_configure_notify   (xcb_generic_event_t *event);
+void _ecore_x_event_handle_configure_request  (xcb_generic_event_t *event);
+void _ecore_x_event_handle_gravity_notify     (xcb_generic_event_t *event);
+void _ecore_x_event_handle_resize_request     (xcb_generic_event_t *event);
+void _ecore_x_event_handle_circulate_notify   (xcb_generic_event_t *event);
+void _ecore_x_event_handle_circulate_request  (xcb_generic_event_t *event);
+void _ecore_x_event_handle_property_notify    (xcb_generic_event_t *event);
+void _ecore_x_event_handle_selection_clear    (xcb_generic_event_t *event);
+void _ecore_x_event_handle_selection_request  (xcb_generic_event_t *event);
+void _ecore_x_event_handle_selection_notify   (xcb_generic_event_t *event);
+void _ecore_x_event_handle_colormap_notify    (xcb_generic_event_t *event);
+void _ecore_x_event_handle_client_message     (xcb_generic_event_t *event);
+void _ecore_x_event_handle_mapping_notify     (xcb_generic_event_t *event);
+#ifdef ECORE_XCB_DAMAGE
+void _ecore_x_event_handle_damage_notify      (xcb_generic_event_t *event);
+#endif /* ECORE_XCB_DAMAGE */
+#ifdef ECORE_XCB_RANDR
+void _ecore_x_event_handle_randr_change       (xcb_generic_event_t *event);
+#endif /* ECORE_XCB_RANDR */
+#ifdef ECORE_XCB_SCREENSAVER
+void _ecore_x_event_handle_screensaver_notify (xcb_generic_event_t *event);
+#endif /* ECORE_XCB_SCREENSAVER */
+#ifdef ECORE_XCB_SHAPE
+void _ecore_x_event_handle_shape_change       (xcb_generic_event_t *event);
+#endif /* ECORE_XCB_SHAPE */
+#ifdef ECORE_XCB_SYNC
+void _ecore_x_event_handle_sync_counter       (xcb_generic_event_t *event);
+void _ecore_x_event_handle_sync_alarm         (xcb_generic_event_t *event);
+#endif /* ECORE_XCB_SYNC */
+#ifdef ECORE_XCB_FIXES
+void _ecore_x_event_handle_fixes_selection_notify(xcb_generic_event_t *event);
+#endif /* ECORE_XCB_FIXES */
+
+
+/* requests / replies */
+int          _ecore_x_reply_init ();
+void         _ecore_x_reply_shutdown ();
+void         _ecore_xcb_cookie_cache (unsigned int cookie);
+unsigned int _ecore_xcb_cookie_get (void);
+void         _ecore_xcb_reply_cache (void *reply);
+void        *_ecore_xcb_reply_get (void);
+
+
+/* atoms */
+extern Ecore_X_Atom ECORE_X_ATOM_ATOM;
+extern Ecore_X_Atom ECORE_X_ATOM_CARDINAL;
+extern Ecore_X_Atom ECORE_X_ATOM_STRING;
+extern Ecore_X_Atom ECORE_X_ATOM_WINDOW;
+extern Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE;
+extern Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS;
+
+#define ECORE_X_ATOMS_COUNT 117
+
+void _ecore_x_atom_init          (xcb_intern_atom_cookie_t *);
+void _ecore_x_atom_init_finalize (xcb_intern_atom_cookie_t *);
+
+
+/* damage */
+void _ecore_x_damage_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_damage_init_finalize (void);
+
+/* composite */
+void _ecore_x_composite_init       (const xcb_query_extension_reply_t *reply);
+void _ecore_x_composite_init_finalize (void);
+
+/* from dnd */
+void                _ecore_x_dnd_init       (void);
+void                _ecore_x_dnd_shutdown   (void);
+Ecore_X_DND_Source *_ecore_x_dnd_source_get (void);
+Ecore_X_DND_Target *_ecore_x_dnd_target_get (void);
+void                _ecore_x_dnd_drag       (Ecore_X_Window root,
+                                             int x,
+                                             int y);
+
+
+/* dpms */
+void _ecore_x_dpms_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_dpms_init_finalize (void);
+
+
+/* netwm */
+Ecore_X_Window_State _ecore_x_netwm_state_get(Ecore_X_Atom a);
+int                  _ecore_x_netwm_startup_info_begin(Ecore_X_Window win, char *data);
+int                  _ecore_x_netwm_startup_info(Ecore_X_Window win, char *data);
+
+
+/* randr */
+void _ecore_x_randr_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_randr_init_finalize (void);
+
+
+/* selection */
+void                      _ecore_x_selection_init(void);
+void                      _ecore_x_selection_shutdown(void);
+Ecore_X_Atom              _ecore_x_selection_target_atom_get(const char *target);
+char                     *_ecore_x_selection_target_get(Ecore_X_Atom target);
+Ecore_X_Selection_Intern *_ecore_x_selection_get(Ecore_X_Atom selection);
+int                       _ecore_x_selection_set(Ecore_X_Window w, const void *data, int len, Ecore_X_Atom selection);
+int                       _ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret);
+void                     *_ecore_x_selection_parse(const char *target, void *data, int size, int format);
+
+
+/* screensaver */
+void _ecore_x_screensaver_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_screensaver_init_finalize (void);
+
+
+/* shape */
+void _ecore_x_shape_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_shape_init_finalize (void);
+
+
+/* sync */
+void _ecore_x_sync_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_sync_init_finalize (void);
+
+
+/* xfixes */
+void _ecore_x_xfixes_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_xfixes_init_finalize (void);
+
+
+/* xinerama */
+void _ecore_x_xinerama_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_xinerama_init_finalize (void);
+
+
+/* xprint */
+void _ecore_x_xprint_init          (const xcb_query_extension_reply_t *reply);
+void _ecore_x_xprint_init_finalize (void);
+
+/* to categorize */
+void _ecore_x_sync_magic_send(int val, Ecore_X_Window swin);
+void _ecore_x_window_grab_remove(Ecore_X_Window win);
+void _ecore_x_key_grab_remove(Ecore_X_Window win);
+
+
+#endif /* __ECORE_XCB_PRIVATE_H__*/
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_randr.c b/src/lib/ecore_x/xcb/ecore_xcb_randr.c
new file mode 100644 (file)
index 0000000..60ef77f
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_RandR_Group X RandR Extension Functions
+ *
+ * Functions related to the X RandR extension.
+ */
+
+
+#ifdef ECORE_XCB_RANDR
+static int _randr_available = 0;
+static xcb_randr_query_version_cookie_t _ecore_xcb_randr_init_cookie;
+#endif /* ECORE_XCB_RANDR */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_randr_init and
+   _ecore_xcb_randr_init_finalize. The first one gets the cookies and
+   the second one gets the replies and set the atoms. */
+
+void
+_ecore_x_randr_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_RANDR
+   if (reply && (reply->present))
+      _ecore_xcb_randr_init_cookie = xcb_randr_query_version_unchecked(_ecore_xcb_conn, 1, 2);
+#endif /* ECORE_XCB_RANDR */
+}
+
+void
+_ecore_x_randr_init_finalize(void)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_query_version_reply_t *reply;
+
+   reply = xcb_randr_query_version_reply(_ecore_xcb_conn,
+                                         _ecore_xcb_randr_init_cookie, NULL);
+
+   if (reply)
+     {
+        if ((reply->major_version >= 1) &&
+            (reply->minor_version >= 1))
+          _randr_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Return whether the X server supports the RandR Extension.
+ * @return 1 if the X RandR Extension is available, 0 otherwise.
+ *
+ * Return 1 if the X server supports the RandR Extension version 1.1,
+ * 0 otherwise.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI int
+ecore_x_randr_query(void)
+{
+#ifdef ECORE_XCB_RANDR
+   return _randr_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
+
+
+static Ecore_X_Window
+_xcb_randr_root_to_screen(Ecore_X_Window root)
+{
+   xcb_screen_iterator_t iter;
+
+   iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
+   for (; iter.rem; xcb_screen_next(&iter))
+     {
+        if (iter.data->root == root)
+          return iter.data->root;
+     }
+
+   return XCB_NONE;
+}
+
+/**
+ * Select if the ScreenChangeNotify events  will be sent.
+ * @param window The window.
+ * @param on     1 to enable, 0 to disable.
+ * @return       1 on success, 0 otherwise.
+ *
+ * If @p on value is @c 1, ScreenChangeNotify events
+ * will be sent when the screen configuration changes, either from
+ * this protocol extension, or due to detected external screen
+ * configuration changes. ScreenChangeNotify may also be sent when
+ * this request executes if the screen configuration has changed since
+ * the client connected, to avoid race conditions.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI int
+ecore_x_randr_events_select(Ecore_X_Window window,
+                            int            on)
+{
+#ifdef ECORE_XCB_RANDR
+     xcb_randr_select_input(_ecore_xcb_conn, window,
+                            on ? XCB_RANDR_SCREEN_CHANGE_NOTIFY : 0);
+     return 1;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Sends the GetScreenInfo request.
+ * @param window Window whose properties are requested.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI void
+ecore_x_randr_get_screen_info_prefetch(Ecore_X_Window window)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_cookie_t cookie;
+
+   cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn,
+                                                _xcb_randr_root_to_screen(window));
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_RANDR */
+}
+
+
+/**
+ * Gets the reply of the GetScreenInfo request sent by ecore_x_randr_get_screen_info_prefetch().
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI void
+ecore_x_randr_get_screen_info_fetch(void)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_cookie_t cookie;
+   xcb_randr_get_screen_info_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply =xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Get the set of rotations and reflections.
+ * @param root The window (Unused).
+ * @return     The set of rotations and reflections.
+ *
+ * Get the set of rotations and reflections supported by the screen
+ * associated to @p window (passed to
+ * ecore_x_randr_get_screen_info_prefetch()).
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Randr_Rotation
+ecore_x_randr_screen_rotations_get(Ecore_X_Window root __UNUSED__)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   return reply->rotations;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Get the rotation.
+ * @param root The window (Unused).
+ * @return     The rotation.
+ *
+ * Get the rotation supported by the screen
+ * associated to @p window (passed to
+ * ecore_x_randr_get_screen_info_prefetch()).
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Randr_Rotation
+ecore_x_randr_screen_rotation_get(Ecore_X_Window root __UNUSED__)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   return reply->rotation;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Get the frame buffer sizes.
+ * @param root The window (Unused).
+ * @param num  The number of sizes.
+ * @return     The sizes.
+ *
+ * Get the list of possible frame buffer sizes (at the normal
+ * orientation supported by the screen associated to @p window (passed
+ * to ecore_x_randr_get_screen_info_prefetch()). Each size indicates
+ * both the linear physical size of the screen and the pixel size.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Screen_Size *
+ecore_x_randr_screen_sizes_get(Ecore_X_Window root __UNUSED__,
+                               int           *num)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+   xcb_randr_screen_size_t           *sizes;
+   Ecore_X_Screen_Size               *ret;
+   int                                n;
+   int                                i;
+
+   if (num) *num = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return NULL;
+
+   n = xcb_randr_get_screen_info_sizes_length(reply);
+   ret = calloc(n, sizeof(Ecore_X_Screen_Size));
+   if (!ret) return NULL;
+
+   if (num) *num = n;
+   sizes = xcb_randr_get_screen_info_sizes(reply);
+   for (i = 0; i < n; i++)
+     {
+        ret[i].width = sizes[i].width;
+        ret[i].height = sizes[i].height;
+     }
+
+   return ret;
+#else
+   if (num) *num = 0;
+   return NULL;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/**
+ * Get the current frame buffer size.
+ * @param root The window (Unused).
+ * @return     The active size.
+ *
+ * Get the active frame buffer size supported by the screen associated
+ * to @p window (passed to
+ * ecore_x_randr_get_screen_info_prefetch()).
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Screen_Size
+ecore_x_randr_current_screen_size_get(Ecore_X_Window root __UNUSED__)
+{
+   Ecore_X_Screen_Size ret = { -1, -1 };
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+   xcb_randr_screen_size_t           *sizes;
+   uint16_t                           size_index;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return ret;
+
+   size_index = reply->sizeID;
+   sizes = xcb_randr_get_screen_info_sizes(reply);
+   if (size_index < reply->nSizes)
+     {
+        ret.width = sizes[size_index].mwidth;
+        ret.height = sizes[size_index].mheight;
+     }
+#endif /* ECORE_XCB_RANDR */
+
+   return ret;
+}
+
+/**
+ * Get the current refresh rate.
+ * @param root The window (Unused).
+ * @return     The current refresh rate.
+ *
+ * Get the current refresh rate supported by the screen associated
+ * to @p window (passed to
+ * ecore_x_randr_get_screen_info_prefetch()).
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Screen_Refresh_Rate
+ecore_x_randr_current_screen_refresh_rate_get(Ecore_X_Window root __UNUSED__)
+{
+   Ecore_X_Screen_Refresh_Rate        ret = { -1 };
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return ret;
+
+   ret.rate = reply->rate;
+#endif /* ECORE_XCB_RANDR */
+
+   return ret;
+}
+
+/**
+ * Get the refresh rates.
+ * @param root The window (Unused).
+ * @param num  The number of refresh rates.
+ * @return     The refresh rates.
+ *
+ * Get the list of refresh rates for each size supported by the screen
+ * associated to @p window (passed to
+ * ecore_x_randr_get_screen_info_prefetch()). Each element
+ * of 'sizes' has a corresponding element in 'refresh'. An empty list
+ * indicates no known rates, or a device for which refresh is not
+ * relevant.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request,
+ * then ecore_x_randr_get_screen_info_fetch(), which gets the reply.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI Ecore_X_Screen_Refresh_Rate *
+ecore_x_randr_screen_refresh_rates_get(Ecore_X_Window root __UNUSED__,
+                                       int            size_id __UNUSED__,
+                                       int           *num)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_get_screen_info_reply_t *reply;
+   Ecore_X_Screen_Refresh_Rate       *ret;
+   Ecore_X_Screen_Refresh_Rate       *tmp;
+   xcb_randr_refresh_rates_iterator_t iter;
+   uint16_t                           n;
+
+   if (num) *num = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return NULL;
+
+   n = reply->nSizes;
+   ret = calloc(n, sizeof(Ecore_X_Screen_Refresh_Rate));
+   if (!ret)
+     return NULL;
+
+   if (num) *num = n;
+
+   /* FIXME: maybe there's a missing function in xcb randr implementation */
+   iter = xcb_randr_get_screen_info_rates_iterator(reply);
+   tmp = ret;
+   for (; iter.rem; xcb_randr_refresh_rates_next(&iter), tmp++)
+     {
+       tmp->rate = iter.data->nRates;;
+     }
+
+   return ret;
+#else
+   if (num) *num = 0;
+   return NULL;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/* FIXME: round trip. Should we remove it ? */
+
+/**
+ * Set the screen rotation.
+ * @param root The root window.
+ * @param rot  The rotation.
+ *
+ * Set the rotation of the screen associated to @p root.
+ *
+ * Note that that function is blocking.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI void
+ecore_x_randr_screen_rotation_set(Ecore_X_Window         root,
+                                  Ecore_X_Randr_Rotation rot)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_set_screen_config_cookie_t cookie;
+   xcb_randr_set_screen_config_reply_t *reply_config;
+   xcb_randr_get_screen_info_reply_t   *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return;
+
+   cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
+                                                  XCB_CURRENT_TIME,
+                                                  reply->config_timestamp,
+                                                  reply->sizeID,
+                                                  rot,
+                                                  0);
+   reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL);
+   if (reply_config)
+     free(reply_config);
+#endif /* ECORE_XCB_RANDR */
+}
+
+/* FIXME: round trip. Should we remove it ? */
+
+/**
+ * Set the screen size.
+ * @param root The root window.
+ * @param size The size.
+ *
+ * Set the size of the screen associated to @p root.
+ *
+ * Note that that function is blocking.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI int
+ecore_x_randr_screen_size_set(Ecore_X_Window      root,
+                              Ecore_X_Screen_Size size)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_set_screen_config_cookie_t cookie;
+   xcb_randr_set_screen_config_reply_t *reply_config;
+   xcb_randr_get_screen_info_reply_t   *reply;
+   xcb_randr_screen_size_iterator_t     iter;
+   int                                  size_index = -1;
+   int                                  i;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   iter = xcb_randr_get_screen_info_sizes_iterator(reply);
+   for (i = 0; iter.rem; xcb_randr_screen_size_next(&iter), i++)
+     {
+        if ((iter.data->width = size.width) &&
+            (iter.data->height = size.height) &&
+            (iter.data->mwidth = size.width) &&
+            (iter.data->mheight = size.height))
+          {
+            size_index = i;
+            break;
+          }
+     }
+   if (size_index == -1) return 0;
+
+   cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
+                                                  XCB_CURRENT_TIME,
+                                                  reply->config_timestamp,
+                                                  size_index,
+                                                  XCB_RANDR_ROTATION_ROTATE_0,
+                                                  0);
+   reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply_config)
+     return 0;
+
+   free(reply_config);
+
+   return 1;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
+
+/* FIXME: round trip. Should we remove it ? */
+
+/**
+ * Set the screen refresh rate.
+ * @param root The root window.
+ * @param size The size.
+ * @param rate The refresh rate.
+ *
+ * Set the size and the refresh rate of the screen associated to
+ * @p root.
+ *
+ * Note that that function is blocking.
+ * @ingroup Ecore_X_RandR_Group
+ */
+EAPI int
+ecore_x_randr_screen_refresh_rate_set(Ecore_X_Window              root,
+                                      Ecore_X_Screen_Size         size,
+                                      Ecore_X_Screen_Refresh_Rate rate)
+{
+#ifdef ECORE_XCB_RANDR
+   xcb_randr_set_screen_config_cookie_t cookie;
+   xcb_randr_set_screen_config_reply_t *reply_config;
+   xcb_randr_get_screen_info_reply_t   *reply;
+   xcb_randr_screen_size_iterator_t     iter;
+   int                                  size_index = -1;
+   int                                  i;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   iter = xcb_randr_get_screen_info_sizes_iterator(reply);
+   for (i = 0; iter.rem; xcb_randr_screen_size_next(&iter), i++)
+     {
+        if ((iter.data->width = size.width) &&
+            (iter.data->height = size.height) &&
+            (iter.data->mwidth = size.width) &&
+            (iter.data->mheight = size.height))
+          {
+            size_index = i;
+            break;
+          }
+     }
+   if (size_index == -1) return 0;
+
+   cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root,
+                                                  XCB_CURRENT_TIME,
+                                                  reply->config_timestamp,
+                                                  size_index,
+                                                  XCB_RANDR_ROTATION_ROTATE_0,
+                                                  rate.rate);
+   reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!reply_config)
+     return 0;
+
+   free(reply_config);
+
+   return 1;
+#else
+   return 0;
+#endif /* ECORE_XCB_RANDR */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_region.c b/src/lib/ecore_x/xcb/ecore_xcb_region.c
new file mode 100644 (file)
index 0000000..24d27a1
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+
+
+/*
+ * [x] XCreateRegion
+ * [ ] XPolygonRegion
+ * [x] XSetRegion
+ * [x] XDestroyRegion
+ *
+ * [x] XOffsetRegion
+ * [ ] XShrinkRegion
+ *
+ * [ ] XClipBox
+ * [x] XIntersectRegion
+ * [x] XUnionRegion
+ * [x] XUnionRectWithRegion
+ * [x] XSubtractRegion
+ * [ ] XXorRegion
+ *
+ * [x] XEmptyRegion
+ * [x] XEqualRegion
+ *
+ * [x] XPointInRegion
+ * [x] XRectInRegion
+ */
+
+EAPI Ecore_X_XRegion *
+ecore_x_xregion_new()
+{
+   pixman_region16_t *region;
+
+   region =  (pixman_region16_t *)malloc (sizeof (pixman_region16_t));
+   if (!region)
+     return NULL;
+
+   pixman_region_init(region);
+
+   return (Ecore_X_XRegion *)region;
+}
+
+EAPI void
+ecore_x_xregion_free(Ecore_X_XRegion *region)
+{
+   if (!region)
+     return;
+
+   pixman_region_fini(region);
+   free(region);
+}
+
+EAPI int
+ecore_x_xregion_set(Ecore_X_XRegion *region, Ecore_X_GC gc)
+{
+   xcb_rectangle_t *rects;
+   pixman_box16_t  *boxes;
+   int              num;
+
+   if (!region)
+     return 0;
+
+   boxes = pixman_region_rectangles ((pixman_region16_t *)region, &num);
+
+   if (!boxes || (num == 0))
+     return 0;
+
+   rects = (xcb_rectangle_t *)malloc(sizeof(xcb_rectangle_t) * num);
+   if (!rects)
+     return 0;
+
+   for (i = 0; i < num; i++)
+     {
+        rects[i].x = boxes[i].x1;
+        rects[i].y = boxes[i].y1;
+        rects[i].width = boxes[i].x2 - boxes[i].x1 + 1;
+        rects[i].height = boxes[i].y2 - boxes[i].y1 + 1;
+     }
+
+   xcb_set_clip_rectangles(_ecore_x_connection,
+                           XCB_CLIP_ORDERING_YX_BANDED,
+                           gc,
+                           0, 0,
+                           num,
+                           rects);
+   return 1;
+}
+
+EAPI void
+ecore_x_xregion_translate(Ecore_X_XRegion *region, int x, int y)
+{
+   if (!region)
+     return;
+
+   pixman_region_translate((pixman_region16_t *)region, x, y);
+}
+
+EAPI int
+ecore_x_xregion_intersect(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   return pixman_region_intersect((pixman_region16_t *)dst, (pixman_region16_t *)r1, (pixman_region16_t *)r2);
+}
+
+EAPI int
+ecore_x_xregion_union(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   return pixman_region_union((pixman_region16_t *)dst, (pixman_region16_t *)r1, (pixman_region16_t *)r2);
+}
+
+EAPI int
+ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, Ecore_X_XRegion *src, Ecore_X_Rectangle *rect)
+{
+   return pixman_region_union_rect((pixman_region16_t *)dst, (pixman_region16_t *)src,
+                                   rect->x, rect->y, rect->width, rect->height);
+}
+
+EAPI int
+ecore_x_xregion_subtract(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   return pixman_region_subtract((pixman_region16_t *)dst, (pixman_region16_t *)rm, (pixman_region16_t *)rs);
+}
+
+EAPI int
+ecore_x_xregion_is_empty(Ecore_X_XRegion *region)
+{
+   if (!region)
+     return 1;
+
+   return !pixman_region_not_empty((pixman_region16_t *)region);
+}
+
+EAPI int
+ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   if (!r1 || !r2)
+     return 0;
+
+   return pixman_region_equal((pixman_region16_t *)r1, (pixman_region16_t *)r2);
+}
+
+EAPI int
+ecore_x_xregion_point_contain(Ecore_X_XRegion *region, int x, int y)
+{
+   if (!region)
+     return 0;
+
+   return pixman_region_contains_point((pixman_region16_t *)region, x, y);
+}
+
+EAPI int
+ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, Ecore_X_Rectangle *rect)
+{
+   pixman_box16_t box;
+
+   if (!region || !rect)
+     return 0;
+
+   box.x1 = rect->x;
+   box.y1 = rect->y;
+   box.x2 = rect->x + rect->width - 1;
+   box.y2 = rect->y + rect->height - 1;
+
+   return pixman_region_contains_rectangle((pixman_region16_t *)region, &box);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_reply.c b/src/lib/ecore_x/xcb/ecore_xcb_reply.c
new file mode 100644 (file)
index 0000000..c9ec11e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <stdlib.h>
+
+
+/* 
+ * FIXME:
+ * - in ecore_xcb_cookie_cache, should provide better error management
+ *   when memory allocation fails
+ * - Use an array instead of a list
+ * - Is ecore_xcb_reply_free really needed ?
+ *   _ecore_xcb_reply_cache frees the current reply and
+ *   _ecore_x_reply_shutdown frees the last reply to free.
+ *   I keep it in case it is need for memory improvements,
+ *   but its code is commented.
+ */
+
+static Eina_List  *_ecore_xcb_cookies = NULL;
+static void       *_ecore_xcb_reply = NULL;
+
+typedef struct _Ecore_Xcb_Data Ecore_Xcb_Data;
+
+struct _Ecore_Xcb_Data
+{
+  unsigned int         cookie;
+};
+
+
+int
+_ecore_x_reply_init ()
+{
+   return 1;
+}
+
+void
+_ecore_x_reply_shutdown ()
+{
+  Ecore_Xcb_Data *data;
+
+  if (_ecore_xcb_reply)
+    free(_ecore_xcb_reply);
+
+   if (!_ecore_xcb_cookies)
+     return;
+
+   EINA_LIST_FREE(_ecore_xcb_cookies, data)
+     free(data);
+}
+
+void
+_ecore_xcb_cookie_cache (unsigned int cookie)
+{
+   Ecore_Xcb_Data *data;
+
+   if (!_ecore_xcb_cookies)
+     return;
+
+   data = (Ecore_Xcb_Data *)malloc(sizeof(Ecore_Xcb_Data));
+   if (!data)
+     return;
+
+   data->cookie = cookie;
+
+   _ecore_xcb_cookies = eina_list_append(_ecore_xcb_cookies, data);
+   if (!eina_list_data_find(_ecore_xcb_cookies, data))
+     {
+        free(data);
+        return;
+     }
+}
+
+unsigned int
+_ecore_xcb_cookie_get (void)
+{
+   Ecore_Xcb_Data *data;
+   unsigned int    cookie;
+
+   if (!_ecore_xcb_cookies)
+     return 0;
+
+   data = eina_list_data_get(_ecore_xcb_cookies);
+   if (!data) return 0;
+
+   _ecore_xcb_cookies = eina_list_remove_list(_ecore_xcb_cookies, _ecore_xcb_cookies);
+        cookie = data->cookie;
+        free(data);
+
+        return cookie;
+}
+
+void
+_ecore_xcb_reply_cache (void *reply)
+{
+   if (_ecore_xcb_reply)
+     free(_ecore_xcb_reply);
+   _ecore_xcb_reply = reply;
+}
+
+void *
+_ecore_xcb_reply_get (void)
+{
+   return _ecore_xcb_reply;
+}
+
+EAPI void
+ecore_xcb_reply_free()
+{
+/*   if (_ecore_xcb_reply) */
+/*     { */
+/*        free(_ecore_xcb_reply); */
+/*        _ecore_xcb_reply = NULL; */
+/*     } */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c b/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c
new file mode 100644 (file)
index 0000000..9dc13a6
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_ScreenSaver_Group X ScreenSaver extension
+ *
+ * These functions use the ScreenSaver extension of the X server
+  */
+
+
+#ifdef ECORE_XCB_SCREENSAVER
+static int _screensaver_available = 0;
+static xcb_screensaver_query_version_cookie_t _ecore_xcb_screensaver_init_cookie;
+#endif /* ECORE_XCB_SCREENSAVER */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_screensaver_init and
+   _ecore_xcb_screensaver_init_finalize. The first one gets the cookies and
+   the second one gets the replies and set the atoms. */
+
+void
+_ecore_x_screensaver_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_SCREENSAVER
+   if (reply && (reply->present))
+      _ecore_xcb_screensaver_init_cookie = xcb_screensaver_query_version_unchecked(_ecore_xcb_conn, 1, 1);
+#endif /* ECORE_XCB_SCREENSAVER */
+}
+
+void
+_ecore_x_screensaver_init_finalize(void)
+{
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_screensaver_query_version_reply_t *reply;
+
+   reply = xcb_screensaver_query_version_reply(_ecore_xcb_conn,
+                                               _ecore_xcb_screensaver_init_cookie, NULL);
+
+   if (reply)
+     {
+        if ((reply->server_major_version >= 1) &&
+            (reply->server_minor_version >= 1))
+          _screensaver_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_SCREENSAVER */
+}
+
+
+/**
+ * Return whether the X server supports the ScreenSaver Extension.
+ * @return 1 if the X ScreenSaver Extension is available, 0 otherwise.
+ *
+ * Return 1 if the X server supports the ScreenSaver Extension version 1.0,
+ * 0 otherwise.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_event_available_get(void)
+{
+   return 1;
+}
+
+
+/**
+ * Sends the QueryInfo request.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_idle_time_prefetch(void)
+{
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_screensaver_query_info_cookie_t cookie;
+
+   cookie = xcb_screensaver_query_info_unchecked(_ecore_xcb_conn, ((xcb_screen_t *)_ecore_xcb_screen)->root);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_SCREENSAVER */
+}
+
+
+/**
+ * Gets the reply of the QueryInfo request sent by ecore_x_get_screensaver_prefetch().
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_idle_time_fetch(void)
+{
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_screensaver_query_info_cookie_t cookie;
+   xcb_screensaver_query_info_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_screensaver_query_info_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_SCREENSAVER */
+}
+
+
+/**
+ * Get the number of seconds since the last input was received.
+ * @return The number of seconds.
+ *
+ * Get the number of milliseconds since the last input was received
+ * from the user on any of the input devices.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_idle_time_get(void)
+{
+  int idle = 0;
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_screensaver_query_info_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+
+   if (!reply) return 0;
+
+   /* FIXME: check if it is ms_since_user_input or ms_until_server */
+   idle = reply->ms_since_user_input / 1000;
+#endif /* ECORE_XCB_SCREENSAVER */
+
+   return idle;
+}
+
+
+/**
+ * Set the parameters of the screen saver.
+ * @param timeout  The timeout, in second.
+ * @param interval The interval, in seconds.
+ * @param blank    0 to disable screen blanking, otherwise enable it.
+ * @param expose   Allow Expose generation event or not.
+ *
+ * Set the parameters of the screen saver. @p timeout is the timeout,
+ * in seconds, until the screen saver turns on. @p interval is the
+ * interval, in seconds, between screen saver alterations. @p blank
+ * specifies how to enable screen blanking. @p expose specifies the
+ * screen save control values.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_set(int timeout,
+                        int interval,
+                        int blank,
+                        int expose)
+{
+   xcb_set_screen_saver(_ecore_xcb_conn,
+                        (int16_t)timeout,
+                        (int16_t)interval,
+                        (uint8_t)blank,
+                        (uint8_t)expose);
+}
+
+
+/**
+ * Sends the GetScreenSaver request.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_get_screensaver_prefetch(void)
+{
+   xcb_get_screen_saver_cookie_t cookie;
+
+   cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetScreenSaver request sent by ecore_x_get_screensaver_prefetch().
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_get_screensaver_fetch(void)
+{
+   xcb_get_screen_saver_cookie_t cookie;
+   xcb_get_screen_saver_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+
+/**
+ * Set the timeout of the screen saver.
+ * @param  timeout The timeout to set.
+ *
+ * Set the @p timeout, in seconds, until the screen saver turns on.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_timeout_set(int timeout)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_set_screen_saver(_ecore_xcb_conn,
+                        (int16_t)timeout,
+                        reply->interval,
+                        reply->prefer_blanking,
+                        reply->allow_exposures);
+}
+
+
+/**
+ * Get the timeout of the screen saver.
+ * @return The timeout.
+ *
+ * Get the @p timeout, in seconds, until the screen saver turns on.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_timeout_get(void)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0.0;
+
+   return (int)reply->timeout;
+}
+
+
+/**
+ * Set the interval of the screen saver.
+ * @param  interval The interval to set.
+ *
+ * Set the @p interval, in seconds, between screen saver alterations.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_interval_set(int interval)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_set_screen_saver(_ecore_xcb_conn,
+                        reply->timeout,
+                        (int16_t)interval,
+                        reply->prefer_blanking,
+                        reply->allow_exposures);
+}
+
+
+/**
+ * Get the interval of the screen saver.
+ * @return The interval.
+ *
+ * Get the @p interval, in seconds, between screen saver alterations.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_interval_get(void)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0.0;
+
+   return (int)reply->interval;
+}
+
+
+/**
+ * Set the screen blanking.
+ * @param  blank The blank to set.
+ *
+ * @p blank specifies how to enable screen blanking.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_blank_set(int blank)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_set_screen_saver(_ecore_xcb_conn,
+                        reply->timeout,
+                        reply->interval,
+                        (uint8_t)blank,
+                        reply->allow_exposures);
+}
+
+
+/**
+ * Get the screen blanking.
+ * @return The blanking.
+ *
+ * Get the screen blanking.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_blank_get(void)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0.0;
+
+   return (int)reply->prefer_blanking;
+}
+
+
+/**
+ * Set the screen save control values.
+ * @param  expose The expose to set.
+ *
+ * Set the screen save control values.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_expose_set(int expose)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return;
+
+   xcb_set_screen_saver(_ecore_xcb_conn,
+                        reply->timeout,
+                        reply->interval,
+                        reply->prefer_blanking,
+                        (uint8_t)expose);
+}
+
+
+/**
+ * Get the screen save control values.
+ * @return The expose.
+ *
+ * Get the screen save control values.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request,
+ * then ecore_x_get_screensaver_fetch(), which gets the reply.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI int
+ecore_x_screensaver_expose_get(void)
+{
+   xcb_get_screen_saver_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0.0;
+
+   return (int)reply->allow_exposures;
+}
+
+
+/**
+ * Specifies if the Screen Saver NotifyMask event should be generated.
+ * @param on 0 to disable the generation of the event, otherwise enable it.
+ *
+ * Specifies if the Screen Saver NotifyMask event on the screen
+ * associated with drawable should be generated for this client. If
+ * @p on is set to @c 0, the generation is disabled, otherwise, it is
+ * enabled.
+ * @ingroup Ecore_X_ScreenSaver_Group
+ */
+EAPI void
+ecore_x_screensaver_event_listen_set(int on)
+{
+#ifdef ECORE_XCB_SCREENSAVER
+   xcb_screensaver_select_input(_ecore_xcb_conn,
+                                ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                on ? XCB_SCREENSAVER_EVENT_NOTIFY_MASK : 0);
+#endif /* ECORE_XCB_SCREENSAVER */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_selection.c b/src/lib/ecore_x/xcb/ecore_xcb_selection.c
new file mode 100644 (file)
index 0000000..d329add
--- /dev/null
@@ -0,0 +1,1064 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <string.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+static Ecore_X_Selection_Intern     selections[4];
+static Ecore_X_Selection_Converter *converters = NULL;
+static Ecore_X_Selection_Parser    *parsers = NULL;
+
+static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
+static int _ecore_x_selection_data_default_free(void *data);
+static void *_ecore_x_selection_parser_files(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_files_free(void *data);
+static void *_ecore_x_selection_parser_text(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_text_free(void *data);
+static void *_ecore_x_selection_parser_targets(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_targets_free(void *data);
+
+#define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
+
+void
+_ecore_x_selection_init(void)
+{
+   /* Initialize global data */
+   memset(selections, 0, sizeof(selections));
+
+   /* Initialize converters */
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
+                                       _ecore_x_selection_converter_text);
+#ifdef X_HAVE_UTF8_STRING
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
+                                       _ecore_x_selection_converter_text);
+#endif
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
+                                       _ecore_x_selection_converter_text);
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
+                                       _ecore_x_selection_converter_text);
+
+   /* Initialize parsers */
+   ecore_x_selection_parser_add("text/plain",
+                               _ecore_x_selection_parser_text);
+   ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
+                               _ecore_x_selection_parser_text);
+   ecore_x_selection_parser_add("text/uri-list",
+                               _ecore_x_selection_parser_files);
+   ecore_x_selection_parser_add("_NETSCAPE_URL",
+                               _ecore_x_selection_parser_files);
+   ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
+                               _ecore_x_selection_parser_targets);
+}
+
+void
+_ecore_x_selection_shutdown(void)
+{
+   Ecore_X_Selection_Converter *cnv;
+   Ecore_X_Selection_Parser *prs;
+
+   /* free the selection converters */
+   cnv = converters;
+   while (cnv)
+     {
+       Ecore_X_Selection_Converter *tmp;
+
+       tmp = cnv->next;
+       free(cnv);
+       cnv = tmp;
+     }
+   converters = NULL;
+
+   /* free the selection parsers */
+   prs = parsers;
+   while (prs)
+     {
+       Ecore_X_Selection_Parser *tmp;
+
+       tmp = prs;
+       prs = prs->next;
+       free(tmp->target);
+       free(tmp);
+     }
+   parsers = NULL;
+}
+
+Ecore_X_Selection_Intern *
+_ecore_x_selection_get(Ecore_X_Atom selection)
+{
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     return &selections[0];
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     return &selections[1];
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     return &selections[2];
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     return &selections[3];
+   else
+     return NULL;
+}
+
+
+/*
+ * Sends the GetSelectionOwner request.
+ */
+void
+_ecore_xcb_get_selection_owner_prefetch(Ecore_X_Atom selection)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+
+   cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, selection);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/*
+ * Gets the reply of the GetSelectionOwner request sent by _ecore_xcb_get_selection_owner_prefetch().
+ */
+void
+_ecore_xcb_get_selection_owner_fetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+   xcb_get_selection_owner_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * To use this function, you must call before, and in order,
+ * _ecore_xcb_get_selection_owner_prefetch(), which sends the GetSelectionOwner request,
+ * then _ecore_xcb_get_selection_owner_fetch(), which gets the reply.
+ */
+int
+_ecore_x_selection_set(Ecore_X_Window window,
+                       const void    *data,
+                       int            size,
+                       Ecore_X_Atom   selection)
+{
+   xcb_get_selection_owner_reply_t *reply;
+   unsigned char                   *buf = NULL;
+   int                              in;
+
+   xcb_set_selection_owner(_ecore_xcb_conn, window, selection, _ecore_xcb_event_last_time);
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply || (reply->owner != window)) return 0;
+
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     in = 0;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     in = 1;
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     in = 2;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     in = 3;
+   else
+     return 0;
+
+   if (data)
+     {
+       selections[in].win = window;
+       selections[in].selection = selection;
+       selections[in].length = size;
+       selections[in].time = _ecore_xcb_event_last_time;
+
+       buf = malloc(size);
+       memcpy(buf, data, size);
+       selections[in].data = buf;
+     }
+   else
+     {
+       if (selections[in].data)
+         {
+            free(selections[in].data);
+            memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
+         }
+     }
+
+   return 1;
+}
+
+
+/**
+ * Sends the GetSelectionOwner request.
+ */
+EAPI void
+ecore_x_selection_primary_prefetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+
+   cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_PRIMARY);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_primary_prefetch().
+ */
+EAPI void
+ecore_x_selection_primary_fetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+   xcb_get_selection_owner_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Claim ownership of the PRIMARY selection and set its data.
+ * @param window The window to which this selection belongs
+ * @param data   The data associated with the selection
+ * @param size   The size of the data buffer in bytes
+ * @return       Returns 1 if the ownership of the selection was successfully
+ *               claimed, or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_primary_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_primary_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_primary_set(Ecore_X_Window window,
+                              const void    *data,
+                              int            size)
+{
+   return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
+}
+
+/**
+ * Release ownership of the primary selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_primary_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_primary_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_primary_clear(void)
+{
+   return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
+}
+
+
+/**
+ * Sends the GetSelectionOwner request.
+ */
+EAPI void
+ecore_x_selection_secondary_prefetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+
+   cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_SECONDARY);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_secondary_prefetch().
+ */
+EAPI void
+ecore_x_selection_secondary_fetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+   xcb_get_selection_owner_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+
+/**
+ * Claim ownership of the SECONDARY selection and set its data.
+ * @param window The window to which this selection belongs
+ * @param data   The data associated with the selection
+ * @param size   The size of the data buffer in bytes
+ * @return       Returns 1 if the ownership of the selection was successfully
+ *               claimed, or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_secondary_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_secondary_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_secondary_set(Ecore_X_Window window,
+                                const void    *data,
+                                int            size)
+{
+   return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_SECONDARY);
+}
+
+/**
+ * Release ownership of the secondary selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_secondary_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_secondary_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_secondary_clear(void)
+{
+   return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY);
+}
+
+
+/**
+ * Sends the GetSelectionOwner request.
+ */
+EAPI void
+ecore_x_selection_xdnd_prefetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+
+   cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_XDND);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_xdnd_prefetch().
+ */
+EAPI void
+ecore_x_selection_xdnd_fetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+   xcb_get_selection_owner_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Claim ownership of the XDND selection and set its data.
+ * @param window The window to which this selection belongs
+ * @param data   The data associated with the selection
+ * @param size   The size of the data buffer in bytes
+ * @return       Returns 1 if the ownership of the selection was successfully
+ *               claimed, or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_xdnd_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_xdnd_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_xdnd_set(Ecore_X_Window window,
+                           const void    *data,
+                           int            size)
+{
+   return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_XDND);
+}
+
+/**
+ * Release ownership of the XDND selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_xdnd_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_xdnd_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_xdnd_clear(void)
+{
+   return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
+}
+
+
+/**
+ * Sends the GetSelectionOwner request.
+ */
+EAPI void
+ecore_x_selection_clipboard_prefetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+
+   cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_CLIPBOARD);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_clipboard_prefetch().
+ */
+EAPI void
+ecore_x_selection_clipboard_fetch(void)
+{
+   xcb_get_selection_owner_cookie_t cookie;
+   xcb_get_selection_owner_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Claim ownership of the CLIPBOARD selection and set its data.
+ * @param window The window to which this selection belongs
+ * @param data   The data associated with the selection
+ * @param size   The size of the data buffer in bytes
+ * @return       Returns 1 if the ownership of the selection was successfully
+ *               claimed, or 0 if unsuccessful.
+ *
+ * Get the converted data from a previous CLIPBOARD selection
+ * request. The buffer must be freed when done with.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_clipboard_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_clipboard_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_clipboard_set(Ecore_X_Window window,
+                                const void    *data,
+                                int            size)
+{
+   return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD);
+}
+
+/**
+ * Release ownership of the clipboard selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_selection_clipboard_prefetch(), which sends the GetSelectionOwner request,
+ * then ecore_x_selection_clipboard_fetch(), which gets the reply.
+ */
+EAPI int
+ecore_x_selection_clipboard_clear(void)
+{
+   return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD);
+}
+
+
+/* FIXME: roundtrip if target is not handled in the tests */
+Ecore_X_Atom
+_ecore_x_selection_target_atom_get(const char *target)
+{
+   Ecore_X_Atom x_target = XCB_NONE;
+
+   if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
+     x_target = ECORE_X_ATOM_TEXT;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
+     x_target = ECORE_X_ATOM_COMPOUND_TEXT;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
+     x_target = ECORE_X_ATOM_STRING;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
+     x_target = ECORE_X_ATOM_UTF8_STRING;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
+     x_target = ECORE_X_ATOM_FILE_NAME;
+   else
+     {
+        xcb_intern_atom_cookie_t cookie;
+        xcb_intern_atom_reply_t *reply;
+
+        cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
+                                           strlen(target), target);
+        reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
+        if (!reply)
+          return XCB_NONE;
+       x_target = reply->atom;
+        free(reply);
+     }
+
+   return x_target;
+}
+
+
+/* FIXME: roundtrip if target is not handled in the tests */
+char *
+_ecore_x_selection_target_get(Ecore_X_Atom target)
+{
+   if (target == ECORE_X_ATOM_FILE_NAME)
+     return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
+   else if (target == ECORE_X_ATOM_STRING)
+     return strdup(ECORE_X_SELECTION_TARGET_STRING);
+   else if (target == ECORE_X_ATOM_UTF8_STRING)
+     return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
+   else if (target == ECORE_X_ATOM_TEXT)
+     return strdup(ECORE_X_SELECTION_TARGET_TEXT);
+   else
+     {
+        xcb_get_atom_name_cookie_t cookie;
+        xcb_get_atom_name_reply_t *reply;
+        char                      *name;
+
+        cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, target);
+        reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL);
+        if (!reply)
+          return NULL;
+        name = (char *)malloc(sizeof(char) * (reply->length + 1));
+        if (!name)
+          {
+             free(reply);
+             return NULL;
+          }
+        memcpy(name, xcb_get_atom_name_name(reply), reply->length);
+        name[reply->length] = '\0';
+        free(reply);
+        return name;
+     }
+}
+
+static void
+_ecore_x_selection_request(Ecore_X_Window window,
+                           Ecore_X_Atom   selection,
+                           const char    *target_str)
+{
+   Ecore_X_Atom target, prop;
+
+   target = _ecore_x_selection_target_atom_get(target_str);
+
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
+   else
+     return;
+
+   xcb_convert_selection(_ecore_xcb_conn, window,
+                         selection, target, prop,
+                         XCB_CURRENT_TIME);
+}
+
+EAPI void
+ecore_x_selection_primary_request(Ecore_X_Window window,
+                                  const char    *target)
+{
+   _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_PRIMARY, target);
+}
+
+EAPI void
+ecore_x_selection_secondary_request(Ecore_X_Window window,
+                                    const char    *target)
+{
+   _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_SECONDARY, target);
+}
+
+EAPI void
+ecore_x_selection_xdnd_request(Ecore_X_Window window,
+                               const char    *target)
+{
+   Ecore_X_Atom        atom;
+   Ecore_X_DND_Target *_target;
+
+   _target = _ecore_x_dnd_target_get();
+   atom = _ecore_x_selection_target_atom_get(target);
+   xcb_convert_selection(_ecore_xcb_conn, window,
+                         ECORE_X_ATOM_SELECTION_XDND, atom,
+                         ECORE_X_ATOM_SELECTION_PROP_XDND,
+                         _target->time);
+}
+
+EAPI void
+ecore_x_selection_clipboard_request(Ecore_X_Window window, const char *target)
+{
+   _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
+}
+
+EAPI void
+ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
+                                     int        (*func)(char  *target,
+                                                        void  *data,
+                                                        int    size,
+                                                        void **data_ret,
+                                                        int   *size_ret))
+{
+   Ecore_X_Selection_Converter *cnv;
+
+   cnv = converters;
+   if (converters)
+     {
+       while (1)
+         {
+            if (cnv->target == target)
+              {
+                 cnv->convert = func;
+                 return;
+              }
+            if (cnv->next)
+              cnv = cnv->next;
+            else
+              break;
+         }
+
+       cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
+       cnv = cnv->next;
+     }
+   else
+     {
+       converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
+       cnv = converters;
+     }
+   cnv->target = target;
+   cnv->convert = func;
+}
+
+EAPI void
+ecore_x_selection_converter_add(char *target,
+                                int (*func)(char  *target,
+                                            void  *data,
+                                            int    size,
+                                            void **data_ret,
+                                            int   *size_ret))
+{
+   Ecore_X_Atom x_target;
+
+   if (!func || !target)
+     return;
+
+   x_target = _ecore_x_selection_target_atom_get(target);
+
+   ecore_x_selection_converter_atom_add(x_target, func);
+}
+
+EAPI void
+ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
+{
+   Ecore_X_Selection_Converter *cnv, *prev_cnv;
+
+   prev_cnv = NULL;
+   cnv = converters;
+
+   while (cnv)
+     {
+       if (cnv->target == target)
+         {
+            if (prev_cnv)
+              prev_cnv->next = cnv->next;
+            else
+              converters = cnv->next; /* This was the first converter */
+            free(cnv);
+
+            return;
+         }
+       prev_cnv = cnv;
+       cnv = cnv->next;
+     }
+}
+
+EAPI void
+ecore_x_selection_converter_del(char *target)
+{
+   Ecore_X_Atom x_target;
+
+   if (!target)
+     return;
+
+   x_target = _ecore_x_selection_target_atom_get(target);
+   ecore_x_selection_converter_atom_del(x_target);
+}
+
+EAPI int
+ecore_x_selection_notify_send(Ecore_X_Window requestor,
+                              Ecore_X_Atom   selection,
+                              Ecore_X_Atom   target,
+                              Ecore_X_Atom   property,
+                              Ecore_X_Time   time)
+{
+   xcb_selection_notify_event_t ev;
+
+   ev.time = time;
+   ev.requestor = requestor;
+   ev.selection = selection;
+   ev.target = target;
+   ev.property = property;
+   /* send_event is bit 7 (0x80) of response_type */
+   ev.response_type = 0x80;
+
+   xcb_send_event(_ecore_xcb_conn, 0,
+                  requestor, 0, (const char *)&ev);
+   return 1;
+}
+
+/* Locate and run conversion callback for specified selection target */
+EAPI int
+ecore_x_selection_convert(Ecore_X_Atom selection,
+                          Ecore_X_Atom target,
+                          void       **data_ret)
+{
+   Ecore_X_Selection_Intern    *sel;
+   Ecore_X_Selection_Converter *cnv;
+   void                        *data;
+   char                        *tgt_str;
+   int                          size;
+
+   sel = _ecore_x_selection_get(selection);
+   tgt_str = _ecore_x_selection_target_get(target);
+
+   for (cnv = converters; cnv; cnv = cnv->next)
+     {
+       if (cnv->target == target)
+         {
+            int r;
+            r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
+            free(tgt_str);
+            if (r)
+              {
+                 *data_ret = data;
+                 return r;
+              }
+            else
+              return 0;
+         }
+     }
+
+   /* Default, just return the data */
+   *data_ret = malloc(sel->length);
+   memcpy(*data_ret, sel->data, sel->length);
+   free(tgt_str);
+   return 1;
+}
+
+/* TODO: We need to work out a mechanism for automatic conversion to any requested
+ * locale using Ecore_Txt functions */
+/* Converter for standard non-utf8 text targets */
+static int
+_ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret)
+{
+
+  /* FIXME: to do... */
+
+/*    XTextProperty text_prop; */
+/*    char *mystr; */
+/*    XICCEncodingStyle style; */
+
+/*    if (!data || !size) */
+/*      return 0; */
+
+/*    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) */
+/*      style = XTextStyle; */
+/*    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) */
+/*      style = XCompoundTextStyle; */
+/*    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) */
+/*      style = XStringStyle; */
+/* #ifdef X_HAVE_UTF8_STRING */
+/*    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) */
+/*      style = XUTF8StringStyle; */
+/* #endif */
+/*    else */
+/*      return 0; */
+
+/*    if (!(mystr = strdup(data))) */
+/*      return 0; */
+
+/* #ifdef X_HAVE_UTF8_STRING */
+/*    if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) */
+/*      { */
+/*     int bufsize = strlen((char *)text_prop.value) + 1; */
+/*     *data_ret = malloc(bufsize); */
+/*     memcpy(*data_ret, text_prop.value, bufsize); */
+/*     *size_ret = bufsize; */
+/*     XFree(text_prop.value); */
+/*     free(mystr); */
+/*     return 1; */
+/*      } */
+/* #else */
+/*    if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) */
+/*      { */
+/*     int bufsize = strlen(text_prop.value) + 1; */
+/*     *data_ret = malloc(bufsize); */
+/*     memcpy(*data_ret, text_prop.value, bufsize); */
+/*     *size_ret = bufsize; */
+/*     XFree(text_prop.value); */
+/*     free(mystr); */
+/*     return 1; */
+/*      } */
+/* #endif */
+/*    else */
+/*      { */
+/*     free(mystr); */
+/*     return 0; */
+/*      } */
+
+  return 0;
+}
+
+EAPI void
+ecore_x_selection_parser_add(const char *target,
+                             void     *(*func)(const char *target,
+                                               void       *data,
+                                               int         size,
+                                               int         format))
+{
+   Ecore_X_Selection_Parser *prs;
+
+   if (!target)
+     return;
+
+   prs = parsers;
+   if (parsers)
+     {
+       while (prs->next)
+         {
+            if (!strcmp(prs->target, target))
+              {
+                 prs->parse = func;
+                 return;
+              }
+            prs = prs->next;
+         }
+
+       prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
+       prs = prs->next;
+     }
+   else
+     {
+       parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
+       prs = parsers;
+     }
+   prs->target = strdup(target);
+   prs->parse = func;
+}
+
+EAPI void
+ecore_x_selection_parser_del(const char *target)
+{
+   Ecore_X_Selection_Parser *prs, *prev_prs;
+
+   if (!target)
+     return;
+
+   prev_prs = NULL;
+   prs = parsers;
+
+   while (prs)
+     {
+       if (!strcmp(prs->target, target))
+         {
+            if (prev_prs)
+              prev_prs->next = prs->next;
+            else
+              parsers = prs->next; /* This was the first parser */
+            free(prs->target);
+            free(prs);
+
+            return;
+         }
+       prev_prs = prs;
+       prs = prs->next;
+     }
+}
+
+/* Locate and run conversion callback for specified selection target */
+void *
+_ecore_x_selection_parse(const char *target, void *data, int size, int format)
+{
+   Ecore_X_Selection_Parser *prs;
+   Ecore_X_Selection_Data *sel;
+
+   for (prs = parsers; prs; prs = prs->next)
+     {
+       if (!strcmp(prs->target, target))
+         {
+            sel = prs->parse(target, data, size, format);
+            return sel;
+         }
+     }
+
+   /* Default, just return the data */
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data));
+   sel->free = _ecore_x_selection_data_default_free;
+   sel->length = size;
+   sel->format = format;
+   sel->data = data;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_default_free(void *data)
+{
+   Ecore_X_Selection_Data *sel;
+
+   sel = data;
+   free(sel->data);
+   free(sel);
+   return 1;
+}
+
+static void *
+_ecore_x_selection_parser_files(const char *target, void *_data, int size, int format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Files *sel;
+   char *data = _data;
+   int i, is;
+   char *tmp;
+
+   if (strcmp(target, "text/uri-list") &&
+       strcmp(target, "_NETSCAPE_URL"))
+     return NULL;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
+
+   if (data[size - 1])
+     {
+       /* Isn't nul terminated */
+       size++;
+       data = realloc(data, size);
+       data[size - 1] = 0;
+     }
+
+   tmp = malloc(size);
+   i = 0;
+   is = 0;
+   while ((is < size) && (data[is]))
+     {
+       if ((i == 0) && (data[is] == '#'))
+         {
+            for (; ((data[is]) && (data[is] != '\n')); is++);
+         }
+       else
+         {
+            if ((data[is] != '\r') &&
+                (data[is] != '\n'))
+              {
+                 tmp[i++] = data[is++];
+              }
+            else
+              {
+                 while ((data[is] == '\r') || (data[is] == '\n')) is++;
+                 tmp[i] = 0;
+                 sel->num_files++;
+                 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
+                 sel->files[sel->num_files - 1] = strdup(tmp);
+                 tmp[0] = 0;
+                 i = 0;
+              }
+         }
+     }
+   if (i > 0)
+     {
+       tmp[i] = 0;
+       sel->num_files++;
+       sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
+       sel->files[sel->num_files - 1] = strdup(tmp);
+     }
+   free(tmp);
+   free(data);
+
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
+   ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
+
+   return ECORE_X_SELECTION_DATA(sel);
+}
+
+static int
+_ecore_x_selection_data_files_free(void *data)
+{
+   Ecore_X_Selection_Data_Files *sel;
+   int i;
+
+   sel = data;
+   if (sel->files)
+     {
+       for (i = 0; i < sel->num_files; i++)
+         free(sel->files[i]);
+       free(sel->files);
+     }
+   free(sel);
+   return 0;
+}
+
+static void *
+_ecore_x_selection_parser_text(const char *target __UNUSED__,
+                               void       *_data,
+                               int         size,
+                               int         format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Text *sel;
+   char                        *data = _data;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
+
+   if (data[size - 1])
+     {
+       /* Isn't nul terminated */
+       size++;
+       data = realloc(data, size);
+       data[size - 1] = 0;
+     }
+
+   sel->text = (char *)data;
+   ECORE_X_SELECTION_DATA(sel)->length = size;
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_text_free(void *data)
+{
+   Ecore_X_Selection_Data_Text *sel;
+
+   sel = data;
+   free(sel->text);
+   free(sel);
+   return 1;
+}
+
+static void *
+_ecore_x_selection_parser_targets(const char *target __UNUSED__,
+                                  void       *data,
+                                  int         size,
+                                  int         format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Targets *sel;
+   uint32_t                       *targets;
+   xcb_get_atom_name_cookie_t     *cookies;
+   int                             i;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
+   targets = (uint32_t *)data;
+
+   sel->num_targets = size - 2;
+   sel->targets = malloc((size - 2) * sizeof(char *));
+   cookies = (xcb_get_atom_name_cookie_t *)malloc ((size - 2) * sizeof (xcb_get_atom_name_cookie_t));
+   for (i = 0; i < size - 2; i++)
+     cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, targets[i + 2]);
+
+   /* FIXME: do we let the declaration of reply inside the loop ? */
+   for (i = 0; i < size - 2; i++)
+     {
+       xcb_get_atom_name_reply_t *reply;
+       char                      *name;
+       int                        length;
+
+       reply =xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL);
+       length = xcb_get_atom_name_name_length(reply);
+       name = (char *)malloc (length + 1);
+       memcpy(name, xcb_get_atom_name_name(reply), length);
+       name[length] = '\0';
+       sel->targets[i - 2] = name;
+     }
+   free(cookies);
+   free(data);
+
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
+   ECORE_X_SELECTION_DATA(sel)->length = size;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_targets_free(void *data)
+{
+   Ecore_X_Selection_Data_Targets *sel;
+   int i;
+
+   sel = data;
+
+   if (sel->targets)
+     {
+       for (i = 0; i < sel->num_targets; i++)
+         free(sel->targets[i]);
+       free(sel->targets);
+     }
+   free(sel);
+   return 1;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_shape.c b/src/lib/ecore_x/xcb/ecore_xcb_shape.c
new file mode 100644 (file)
index 0000000..c0f2486
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Shape_Group X Shape extension
+ *
+ * Functions that use the shape extension of the X server to change shape of given windows.
+ */
+
+
+#ifdef ECORE_XCB_SHAPE
+static int _shape_available = 0;
+static xcb_shape_query_version_cookie_t _ecore_xcb_shape_init_cookie;
+#endif /* ECORE_XCB_SHAPE */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_shape_init and
+   _ecore_xcb_shape_init_finalize. The first one gets the cookies and
+   the second one gets the replies. */
+
+void
+_ecore_x_shape_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_SHAPE
+   if (reply && (reply->present))
+      _ecore_xcb_shape_init_cookie = xcb_shape_query_version_unchecked(_ecore_xcb_conn);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+void
+_ecore_x_shape_init_finalize(void)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_query_version_reply_t *reply;
+
+   reply = xcb_shape_query_version_reply(_ecore_xcb_conn,
+                                         _ecore_xcb_shape_init_cookie,
+                                         NULL);
+   if (reply)
+     {
+        _shape_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_SHAPE */
+}
+
+
+/**
+ * Sets the shape of the given window to the given pixmap.
+ * @param dest_win    The given window.
+ * @param source_mask A 2-bit depth pixmap that provides the new shape of the window.
+ *
+ * Sets the shape of the window @p dest_win to the pixmap @p source_mask.
+ * @ingroup Ecore_X_Shape_Group
+ */
+EAPI void
+ecore_x_window_shape_mask_set(Ecore_X_Window dest_win,
+                              Ecore_X_Pixmap source_mask)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_mask(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, source_mask);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_window_set(Ecore_X_Window dest_win,
+                                Ecore_X_Window shape_win)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_window_set_xy(Ecore_X_Window dest_win,
+                                   Ecore_X_Window shape_win,
+                                   int            x,
+                                   int            y)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+
+/**
+ * Sets the shape of the given window to a rectangle.
+ * @param dest_win The given window.
+ * @param x        The X coordinate of the top left corner of the rectangle.
+ * @param y        The Y coordinate of the top left corner of the rectangle.
+ * @param width    The width of the rectangle.
+ * @param height   The height of the rectangle.
+ *
+ * Sets the shape of the window @p dest_win to a rectangle defined  by
+ * @p x, @p y, @p width and @p height.
+ * @ingroup Ecore_X_Shape_Group
+ */
+EAPI void
+ecore_x_window_shape_rectangle_set(Ecore_X_Window dest_win,
+                                   int            x,
+                                   int            y,
+                                   int            width,
+                                   int            height)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_rectangle_t rect;
+
+   rect.x = x;
+   rect.y = y;
+   rect.width = width;
+   rect.height = height;
+   xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_rectangles_set(Ecore_X_Window     dest_win,
+                                    Ecore_X_Rectangle *rects,
+                                    int                num)
+{
+#ifdef ECORE_XCB_SHAPE
+   if (num > 0)
+     xcb_shape_rectangles(_ecore_xcb_conn,
+                          XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
+                          0, dest_win, 0, 0, num, (xcb_rectangle_t *)rects);
+   else
+     xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_window_add(Ecore_X_Window dest_win,
+                                Ecore_X_Window shape_win)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_window_add_xy(Ecore_X_Window dest_win,
+                                   Ecore_X_Window shape_win,
+                                   int            x,
+                                   int            y)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_rectangle_add(Ecore_X_Window dest_win,
+                                   int            x,
+                                   int            y,
+                                   int            width,
+                                   int            height)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_rectangle_t rect;
+
+   rect.x = x;
+   rect.y = y;
+   rect.width = width;
+   rect.height = height;
+   xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_rectangle_clip(Ecore_X_Window dest_win,
+                                    int            x,
+                                    int            y,
+                                    int            width,
+                                    int            height)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_rectangle_t rect;
+   
+   rect.x = x;
+   rect.y = y;
+   rect.width = width;
+   rect.height = height;
+   xcb_shape_rectangles(_ecore_xcb_conn,
+                        XCB_SHAPE_SO_INTERSECT, XCB_SHAPE_SK_BOUNDING,
+                        0, dest_win, 0, 0, 1, &rect);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+EAPI void
+ecore_x_window_shape_rectangles_add(Ecore_X_Window     dest_win,
+                                    Ecore_X_Rectangle *rects,
+                                    int                num)
+{
+#ifdef ECORE_XCB_SHAPE
+   if (num > 0)
+     xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, num, (const xcb_rectangle_t *)rects);
+   else
+     xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+
+/**
+ * Sends the ShapeGetRectangles request.
+ * @param window Requested window.
+ * @ingroup Ecore_X_Shape_Group
+ */
+EAPI void
+ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Window window)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_get_rectangles_cookie_t cookie;
+
+   cookie = xcb_shape_get_rectangles_unchecked(_ecore_xcb_conn, window, XCB_SHAPE_SK_BOUNDING);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+
+/**
+ * Gets the reply of the ShapeGetRectangles request sent by ecore_x_window_shape_rectangles_get_prefetch().
+ * @ingroup Ecore_X_Shape_Group
+ */
+EAPI void
+ecore_x_window_shape_rectangles_get_fetch(void)
+{
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_get_rectangles_cookie_t cookie;
+   xcb_shape_get_rectangles_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_shape_get_rectangles_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+
+/**
+ * To document.
+ * @param  window  Unused.
+ * @param  num_ret To document.
+ * @return         To document.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_window_shape_rectangles_get_prefetch(), which sends the ShapeGetRectangles request,
+ * then ecore_x_window_shape_rectangles_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Shape_Group
+ */
+EAPI Ecore_X_Rectangle *
+ecore_x_window_shape_rectangles_get(Ecore_X_Window window __UNUSED__,
+                                    int           *num_ret)
+{
+   Ecore_X_Rectangle *rects = NULL;
+   uint32_t           num = 0;
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_get_rectangles_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     {
+       if (num_ret) *num_ret = 0;
+       return NULL;
+     }
+
+   num = reply->rectangles_len;
+   rects = malloc(sizeof(Ecore_X_Rectangle) * num);
+   if (rects)
+     memcpy (rects,
+             xcb_shape_get_rectangles_rectangles(reply),
+             num * sizeof (Ecore_X_Rectangle));
+   else
+     num = 0;
+#endif /* ECORE_XCB_SHAPE */
+
+   if (num_ret) *num_ret = num;
+
+   return rects;
+}
+
+EAPI void
+ecore_x_window_shape_events_select(Ecore_X_Window dest_win,
+                                   int            on)
+{
+#ifdef ECORE_XCB_SHAPE
+     xcb_shape_select_input(_ecore_xcb_conn, dest_win, on ? 1 : 0);
+#endif /* ECORE_XCB_SHAPE */
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_sync.c b/src/lib/ecore_x/xcb/ecore_xcb_sync.c
new file mode 100644 (file)
index 0000000..d3a22dd
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Sync_Group X Sync Extension Functions
+ *
+ * Functions related to the X Sync extension.
+ */
+
+
+#ifdef ECORE_XCB_SYNC
+static int _sync_available = 0;
+static xcb_sync_initialize_cookie_t _ecore_xcb_sync_init_cookie;
+#endif /* ECORE_XCB_SYNC */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_sync_init and
+   _ecore_xcb_sync_init_finalize. The first one gets the cookies and
+   the second one gets the replies and set the atoms. */
+
+void
+_ecore_x_sync_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_SYNC
+   if (reply && (reply->present))
+     _ecore_xcb_sync_init_cookie = xcb_sync_initialize_unchecked(_ecore_xcb_conn,
+                                                                 XCB_SYNC_MAJOR_VERSION,
+                                                                 XCB_SYNC_MINOR_VERSION);
+#endif /* ECORE_XCB_SYNC */
+}
+
+void
+_ecore_x_sync_init_finalize(void)
+{
+#ifdef ECORE_XCB_SYNC
+   xcb_sync_initialize_reply_t *reply;
+
+   reply = xcb_sync_initialize_reply(_ecore_xcb_conn,
+                                     _ecore_xcb_sync_init_cookie, NULL);
+
+   if (reply)
+     {
+       if (reply->major_version >= 3)
+        _sync_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_SYNC */
+}
+
+
+/**
+ * Return whether the X server supports the Sync Extension.
+ * @return 1 if the X Sync Extension is available, 0 otherwise.
+ *
+ * Return 1 if the X server supports the Sync Extension version 3.0,
+ * 0 otherwise.
+ * @ingroup Ecore_X_Sync_Group
+ */
+EAPI int
+ecore_x_sync_query(void)
+{
+#ifdef ECORE_XCB_SYNC
+   return _sync_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_SYNC */
+}
+
+
+/**
+ * Create a new alarm.
+ * @param counter A counter.
+ * @return        A newly created alarm.
+ *
+ * Create a new alarm.
+ * @ingroup Ecore_X_Sync_Group
+ */
+EAPI Ecore_X_Sync_Alarm
+ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter)
+{
+#ifdef ECORE_XCB_SYNC
+   uint32_t           value_list[6];
+   xcb_sync_int64_t   init;
+   Ecore_X_Sync_Alarm alarm;
+   uint32_t           value_mask;
+
+   init.lo = 0;
+   init.hi = 0;
+   xcb_sync_set_counter(_ecore_xcb_conn, counter, init);
+
+   value_mask =
+     XCB_SYNC_CA_COUNTER | XCB_SYNC_CA_VALUE_TYPE |
+     XCB_SYNC_CA_VALUE   | XCB_SYNC_CA_TEST_TYPE  |
+     XCB_SYNC_CA_DELTA   | XCB_SYNC_CA_EVENTS;
+   value_list[0] = counter;
+   value_list[1] = XCB_SYNC_VALUETYPE_ABSOLUTE;
+   value_list[2] = 1;
+   value_list[3] = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON;
+   value_list[4] = 1;
+   value_list[5] = 1;
+   alarm = xcb_generate_id(_ecore_xcb_conn);
+   xcb_sync_create_alarm(_ecore_xcb_conn,
+                         alarm,
+                         value_mask,
+                         (const uint32_t *)value_list);
+
+   ecore_x_sync();
+   return alarm;
+#else
+   return 0;
+#endif /* ECORE_XCB_SYNC */
+}
+
+
+/**
+ * Delete an alarm.
+ * @param alarm The alarm to delete.
+ * @return      1 on success, 0 otherwise.
+ *
+ * Delete the @p alarm. Returns 1 on success, 0 otherwise.
+ * @ingroup Ecore_X_Sync_Group
+ */
+EAPI int
+ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm)
+{
+#ifdef ECORE_XCB_SYNC
+   xcb_sync_destroy_alarm(_ecore_xcb_conn, alarm);
+   return 1;
+#else
+   return 0;
+#endif /* ECORE_XCB_SYNC */
+}
+
+/* FIXME: round trip */
+
+EAPI int
+ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, unsigned int *val)
+{
+#ifdef ECORE_XCB_SYNC
+  xcb_sync_query_counter_cookie_t cookie;
+  xcb_sync_query_counter_reply_t *reply;
+
+  cookie = xcb_sync_query_counter_unchecked(_ecore_xcb_conn, counter);
+  reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL);
+  if (reply)
+    {
+       *val = (unsigned int)reply->counter_value.lo;
+       free(reply);
+       return 1;
+    }
+#endif /* ECORE_XCB_SYNC */
+
+  return 0;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window.c b/src/lib/ecore_x/xcb/ecore_xcb_window.c
new file mode 100644 (file)
index 0000000..44c27b7
--- /dev/null
@@ -0,0 +1,2024 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <string.h>
+
+#include <Ecore.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+static int             ignore_num = 0;
+static Ecore_X_Window *ignore_list = NULL;
+
+static Ecore_X_Window _ecore_x_window_at_xy_get(Ecore_X_Window  base,
+                                                int16_t         base_x,
+                                                int16_t         base_y,
+                                                int16_t         x,
+                                                int16_t         y,
+                                                Ecore_X_Window *skip,
+                                                int             skip_num);
+
+#ifdef ECORE_XCB_RENDER
+static Ecore_X_Window _ecore_x_window_argb_internal_new(Ecore_X_Window parent,
+                                                        int16_t        x,
+                                                        int16_t        y,
+                                                        uint16_t       w,
+                                                        uint16_t       h,
+                                                        uint8_t        override_redirect,
+                                                        uint8_t        save_under);
+#endif /* ECORE_XCB_RENDER */
+
+
+/**
+ * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
+ *
+ * Functions that can be used to create an X window.
+ */
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_new(Ecore_X_Window parent,
+                   int            x,
+                   int            y,
+                   int            width,
+                   int            height)
+{
+   uint32_t       value_list[9];
+   Ecore_X_Window window;
+   xcb_visualid_t vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
+   uint32_t       value_mask;
+
+   if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   value_mask =
+     XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
+     XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
+     XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE;
+
+   value_list[0]  = XCB_NONE;
+   value_list[1]  = 0;
+   value_list[2]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[3]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
+   value_list[5]  = 0;
+   value_list[6]  = 0;
+   value_list[7]  =
+     XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
+     XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
+     XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
+     XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
+     XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
+
+   window = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_window(_ecore_xcb_conn,
+                   XCB_WINDOW_CLASS_COPY_FROM_PARENT,
+                   window, parent, x, y, width, height, 0,
+                   XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                   vis,
+                   value_mask,
+                   value_list);
+
+   if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) ecore_x_window_defaults_set(window);
+   return window;
+}
+
+/**
+ * Creates a window with the override redirect attribute set to @c True.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_override_new(Ecore_X_Window parent,
+                            int            x,
+                            int            y,
+                            int            width,
+                            int            height)
+{
+   uint32_t         value_list[9];
+   Ecore_X_Window window;
+   xcb_visualid_t   vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
+   uint32_t         value_mask;
+
+   if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   value_mask =
+     XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
+     XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
+     XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE;
+
+   value_list[0]  = XCB_NONE;
+   value_list[1]  = 0;
+   value_list[2]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[3]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
+   value_list[5]  = 1;
+   value_list[6]  = 0;
+   value_list[7]  =
+     XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
+     XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
+     XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
+     XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
+     XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
+
+   window = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_window(_ecore_xcb_conn,
+                   XCB_WINDOW_CLASS_COPY_FROM_PARENT,
+                   window, parent, x, y, width, height, 0,
+                   XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                   vis,
+                   value_mask,
+                   value_list);
+   return window;
+}
+
+/**
+ * Creates a new input window.
+ * @param   parent The parent window to use.    If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_input_new(Ecore_X_Window parent,
+                         int            x,
+                         int            y,
+                         int            width,
+                         int            height)
+{
+   uint32_t         value_list[3];
+   Ecore_X_Window window;
+   xcb_visualid_t   vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT };
+   uint32_t         value_mask;
+
+   if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   value_mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
+
+   value_list[0]  = 1;
+   value_list[1]  =
+     XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
+     XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
+     XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
+     XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
+     XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   value_list[2]  = XCB_EVENT_MASK_NO_EVENT;
+
+   window = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_window(_ecore_xcb_conn,
+                   XCB_WINDOW_CLASS_COPY_FROM_PARENT,
+                   window, parent, x, y, width, height, 0,
+                   XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                   vis,
+                   value_mask,
+                   value_list);
+
+   if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root)
+     {
+     }
+
+   return window;
+}
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   width  Width.
+ * @param   height Height.
+ * @return         The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_manager_argb_new(Ecore_X_Window parent,
+                                int            x,
+                                int            y,
+                                int            width,
+                                int            height)
+{
+   Ecore_X_Window window = 0;
+
+#ifdef ECORE_XCB_RENDER
+   window = _ecore_x_window_argb_internal_new(parent,
+                                              x, y, width, height,
+                                              1, 0);
+#endif /* ECORE_XCB_RENDER */
+
+   return window;
+}
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   width  Width.
+ * @param   height Height.
+ * @return         The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_argb_new(Ecore_X_Window parent,
+                        int            x,
+                        int            y,
+                        int            width,
+                        int            height)
+{
+   Ecore_X_Window window = 0;
+
+#ifdef ECORE_XCB_RENDER
+   window = _ecore_x_window_argb_internal_new(parent,
+                                              x, y, width, height,
+                                              0, 0);
+#endif /* ECORE_XCB_RENDER */
+
+   return window;
+}
+
+/**
+ * Creates a window with the override redirect attribute set to @c True.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   width  Width.
+ * @param   height Height.
+ * @return         The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_override_argb_new(Ecore_X_Window parent,
+                                 int            x,
+                                 int            y,
+                                 int            width,
+                                 int            height)
+{
+   Ecore_X_Window window = 0;
+
+#ifdef ECORE_XCB_RENDER
+   window = _ecore_x_window_argb_internal_new(parent,
+                                              x, y, width, height,
+                                              1, 0);
+#endif /* ECORE_XCB_RENDER */
+
+   return window;
+}
+
+/**
+ * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions
+ *
+ * Functions to destroy X windows.
+ */
+
+/**
+ * Deletes the given window.
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Destroy_Group
+ */
+EAPI void
+ecore_x_window_free(Ecore_X_Window window)
+{
+   /* sorry sir, deleting the root window doesn't sound like
+    * a smart idea.
+    */
+   if (window)
+      xcb_destroy_window(_ecore_xcb_conn, window);
+}
+
+/**
+ * Sends a delete request to the given window.
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Destroy_Group
+ */
+EAPI void
+ecore_x_window_delete_request_send(Ecore_X_Window window)
+{
+   xcb_client_message_event_t ev;
+
+   /* sorry sir, deleting the root window doesn't sound like
+    * a smart idea.
+    */
+   if (window == 0)
+      return;
+
+   ev.response_type = XCB_CLIENT_MESSAGE;
+   ev.format = 32;
+   ev.sequence = 0;
+   ev.window = window;
+   ev.type = ECORE_X_ATOM_WM_PROTOCOLS;
+   ev.data.data32[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
+   ev.data.data32[1] = XCB_CURRENT_TIME;
+
+   xcb_send_event(_ecore_xcb_conn, 0, window,
+                  XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Configure_Group X Window Configure Functions
+ *
+ * Functions to configure X windows.
+ */
+
+
+/**
+ * Configures the given window with the given mask.
+ * @param   window       The given window.
+ * @param   mask         The given mask.
+ * @param   x            The X coordinate of the window.
+ * @param   y            The Y coordinate of the window.
+ * @param   width        The width of the window.
+ * @param   height       The height of the window.
+ * @param   border_width The border width of the window.
+ * @param   sibling      The sibling window of the window.
+ * @param   stack_mode   The stack mode of the window.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_configure(Ecore_X_Window                window,
+                         Ecore_X_Window_Configure_Mask mask,
+                         int                           x,
+                         int                           y,
+                         int                           width,
+                         int                           height,
+                         int                           border_width,
+                         Ecore_X_Window                sibling,
+                         int                           stack_mode)
+{
+   uint32_t *value_list;
+   uint32_t  value_mask;
+   int       length = 0;
+
+   if (!window)
+      return;
+
+   value_mask = mask;
+   for ( ; value_mask; value_mask >>= 1)
+     if (value_mask & 1)
+       length++;
+   value_list = (uint32_t *)malloc(sizeof(uint32_t) * length);
+   if (!value_list)
+      return;
+
+   value_mask = mask;
+   for ( ; value_mask; value_mask >>= 1, value_list++)
+      if (value_mask & 1)
+        {
+          switch (value_mask) {
+          case XCB_CONFIG_WINDOW_X:
+            *value_list = x;
+            break;
+          case XCB_CONFIG_WINDOW_Y:
+            *value_list = y;
+            break;
+          case XCB_CONFIG_WINDOW_WIDTH:
+            *value_list = width;
+            break;
+          case XCB_CONFIG_WINDOW_HEIGHT:
+            *value_list = height;
+            break;
+          case XCB_CONFIG_WINDOW_BORDER_WIDTH:
+            *value_list = border_width;
+            break;
+          case XCB_CONFIG_WINDOW_SIBLING:
+            *value_list = sibling;
+            break;
+          case XCB_CONFIG_WINDOW_STACK_MODE:
+            *value_list = stack_mode;
+            break;
+          }
+        }
+
+   xcb_configure_window(_ecore_xcb_conn, window, mask, value_list);
+   free(value_list);
+}
+
+/**
+ * Moves a window to the position @p x, @p y.
+ *
+ * The position is relative to the upper left hand corner of the
+ * parent window.
+ *
+ * @param   window The window to move.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_move(Ecore_X_Window window,
+                    int            x,
+                    int            y)
+{
+   uint32_t value_list[2];
+   uint32_t value_mask;
+
+   if (!window)
+      return;
+
+   value_mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
+
+   value_list[0] = x;
+   value_list[1] = y;
+
+   xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
+}
+
+/**
+ * Resizes a window.
+ * @param   window The window to resize.
+ * @param   width  New width of the window.
+ * @param   height New height of the window.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_resize(Ecore_X_Window window,
+                      int            width,
+                      int            height)
+{
+   uint32_t value_list[2];
+   uint32_t value_mask;
+
+   if (!window)
+      return;
+
+   if (width < 1) width = 1;
+   if (height < 1) height = 1;
+
+   value_mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
+
+   value_list[0] = width;
+   value_list[1] = height;
+
+   xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
+}
+
+/**
+ * Moves and resizes a window.
+ * @param   window The window to move and resize.
+ * @param   x      New X position of the window.
+ * @param   y      New Y position of the window.
+ * @param   width  New width of the window.
+ * @param   height New height of the window.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_move_resize(Ecore_X_Window window,
+                           int            x,
+                           int            y,
+                           int            width,
+                           int            height)
+{
+   uint32_t value_list[4];
+   uint32_t value_mask;
+
+   if (!window)
+      return;
+
+   if (width < 1) width = 1;
+   if (height < 1) height = 1;
+
+   value_mask =
+     XCB_CONFIG_WINDOW_X     | XCB_CONFIG_WINDOW_Y     |
+     XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
+
+   value_list[0] = x;
+   value_list[1] = y;
+   value_list[2] = width;
+   value_list[3] = height;
+
+   xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list);
+}
+
+/**
+ * Sets the width of the border of the given window.
+ * @param   window       The given window.
+ * @param   border_width The new border width.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_border_width_set(Ecore_X_Window window,
+                                int            border_width)
+{
+   uint32_t value_list;
+
+   /* doesn't make sense to call this on a root window */
+   if (!window)
+      return;
+
+   value_list = border_width;
+
+   xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_BORDER_WIDTH, &value_list);
+}
+
+/**
+ * Raises the given window.
+ * @param   window The window to raise.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_raise(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   if (!window)
+      return;
+
+   value_list = XCB_STACK_MODE_ABOVE;
+
+   xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list);
+}
+
+/**
+ * Lowers the given window.
+ * @param   window The window to lower.
+ * @ingroup Ecore_X_Window_Configure_Group
+ */
+EAPI void
+ecore_x_window_lower(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   if (!window)
+      return;
+
+   value_list = XCB_STACK_MODE_BELOW;
+
+   xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Change_Properties_Group X Window Change Property Functions
+ *
+ * Functions that change window properties.
+ */
+
+/**
+ * Sets the default properties for the given window.
+ *
+ * The default properties set for the window are @c WM_CLIENT_MACHINE and
+ * @c _NET_WM_PID.
+ *
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Change_Property_Group
+ */
+EAPI void
+ecore_x_window_defaults_set(Ecore_X_Window window)
+{
+   char   buf[MAXHOSTNAMELEN];
+   pid_t  pid;
+   int    argc;
+   char **argv;
+
+   /*
+    * Set WM_CLIENT_MACHINE.
+    */
+   gethostname(buf, MAXHOSTNAMELEN);
+   buf[MAXHOSTNAMELEN - 1] = '\0';
+   /* The ecore function uses UTF8 which Xlib may not like (especially
+    * with older clients) */
+   /* ecore_xcb_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
+                                 (char *)buf); */
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       ECORE_X_ATOM_WM_CLIENT_MACHINE,
+                       ECORE_X_ATOM_STRING,
+                       8, strlen(buf), buf);
+
+   /*
+    * Set _NET_WM_PID
+    */
+   pid = getpid();
+   ecore_x_netwm_pid_set(window, pid);
+
+   ecore_x_netwm_window_type_set(window, ECORE_X_WINDOW_TYPE_NORMAL);
+
+   ecore_app_args_get(&argc, &argv);
+   ecore_x_icccm_command_set(window, argc, argv);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions
+ *
+ * Functions to change the visibility of X windows.
+ */
+
+/**
+ * Shows a window.
+ *
+ * Synonymous to "mapping" a window in X Window System terminology.
+ *
+ * @param   window The window to show.
+ * @ingroup Ecore_X_Window_Visibility_Group
+ */
+EAPI void
+ecore_x_window_show(Ecore_X_Window window)
+{
+   xcb_map_window(_ecore_xcb_conn, window);
+}
+
+/**
+ * Hides a window.
+ *
+ * Synonymous to "unmapping" a window in X Window System terminology.
+ *
+ * @param   window The window to hide.
+ * @ingroup Ecore_X_Window_Visibility_Group
+ */
+EAPI void
+ecore_x_window_hide(Ecore_X_Window window)
+{
+   xcb_unmap_notify_event_t ev;
+   Ecore_X_Window           root;
+
+   /* ICCCM: SEND unmap event... */
+   root = window;
+   /* FIXME: is it correct ? */
+   if (xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem == 1)
+     root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+   else
+     {
+        xcb_get_geometry_cookie_t   cookie;
+        xcb_get_geometry_reply_t   *rep;
+        Ecore_X_Drawable            draw;
+
+        /* FIXME: can we avoid round trips, here ? */
+        draw = window;
+        cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, draw);
+        rep = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL);
+        if (!rep)
+           return;
+        root = rep->root;
+        free(rep);
+     }
+   ev.response_type = XCB_UNMAP_NOTIFY;
+   ev.pad0 = 0;
+   ev.sequence = 0;
+   ev.event = root;
+   ev.window = window;
+   ev.from_configure = 0;
+
+   xcb_send_event(_ecore_xcb_conn, 0, root,
+                  XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+                  (const char *)&ev);
+   xcb_unmap_window(_ecore_xcb_conn, window);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Input_Focus_Group X Window Input Focus Functions
+ *
+ * Functions that manage the focus of an X Window.
+ */
+
+/**
+ * Sets the focus to the window @p window.
+ * @param   window The window to focus.
+ * @ingroup Ecore_X_Window_Input_Focus_Group
+ */
+EAPI void
+ecore_x_window_focus(Ecore_X_Window window)
+{
+   Ecore_X_Time time = XCB_CURRENT_TIME;
+
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */
+   xcb_set_input_focus(_ecore_xcb_conn,
+                       XCB_INPUT_FOCUS_POINTER_ROOT, window, time);
+}
+
+/**
+ * Sets the focus to the given window at a specific time.
+ * @param   window The window to focus.
+ * @param   time   When to set the focus to the window.
+ * @ingroup Ecore_X_Window_Input_Focus_Group
+ */
+EAPI void
+ecore_x_window_focus_at_time(Ecore_X_Window window,
+                             Ecore_X_Time   time)
+{
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */
+   xcb_set_input_focus(_ecore_xcb_conn,
+                       XCB_INPUT_FOCUS_POINTER_ROOT, window, time);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Reparent_Group X Window Reparent Functions
+ *
+ * Functions that retrieve or changes the parent window of a window.
+ */
+
+/**
+ * Moves a window to within another window at a given position.
+ * @param   window     The window to reparent.
+ * @param   new_parent The new parent window.
+ * @param   x          X position within new parent window.
+ * @param   y          Y position within new parent window.
+ * @ingroup Ecore_X_Window_Reparent_Group
+ */
+EAPI void
+ecore_x_window_reparent(Ecore_X_Window window,
+                        Ecore_X_Window new_parent,
+                        int            x,
+                        int            y)
+{
+   if (new_parent == 0) new_parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   xcb_reparent_window(_ecore_xcb_conn, window, new_parent, x, y);
+}
+
+
+/**
+ * @defgroup Ecore_X_Window_Change_Attributes_Group X Window Change Attributes Functions
+ *
+ * Functions that change the attributes of a window.
+ */
+
+/**
+ * Sets the background pixmap of the given window.
+ * @param   window The given window.
+ * @param   pixmap The pixmap to set to.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_pixmap_set(Ecore_X_Window window,
+                          Ecore_X_Pixmap pixmap)
+{
+   uint32_t value_list;
+
+   value_list = pixmap;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_BACK_PIXMAP, &value_list);
+}
+
+/**
+ * Sets the background color of the given window.
+ * @param   window The given window.
+ * @param   red    The red component of the color to set to.
+ * @param   green  The green component of the color to set to.
+ * @param   blue   The blue component of the color to set to.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_background_color_set(Ecore_X_Window window,
+                                    unsigned short red,
+                                    unsigned short green,
+                                    unsigned short blue)
+{
+   xcb_alloc_color_cookie_t cookie;
+   xcb_alloc_color_reply_t *rep;
+   uint32_t                 value_list;
+
+   /* FIXME: should I provide a reply, and not the color components, here ? */
+   /*        (because of roundtrips) */
+   cookie = xcb_alloc_color_unchecked(_ecore_xcb_conn,
+                                      ((xcb_screen_t *)_ecore_xcb_screen)->default_colormap,
+                                      red, green, blue);
+   rep = xcb_alloc_color_reply(_ecore_xcb_conn, cookie, NULL);
+   if (!rep)
+     return;
+
+   value_list = rep->pixel;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_BACK_PIXEL, &value_list);
+   free(rep);
+}
+
+/**
+ * Sets the bit gravity of the given window.
+ * @param   window  The given window.
+ * @param   gravity The gravity.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_pixel_gravity_set(Ecore_X_Window  window,
+                                 Ecore_X_Gravity gravity)
+{
+   uint32_t value_list;
+
+   value_list = gravity;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_BIT_GRAVITY, &value_list);
+}
+
+/**
+ * Sets the gravity of the given window.
+ * @param   window  The given window.
+ * @param   gravity The gravity.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_gravity_set(Ecore_X_Window  window,
+                           Ecore_X_Gravity gravity)
+{
+   uint32_t value_list;
+
+   value_list = gravity;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_WIN_GRAVITY, &value_list);
+}
+
+/**
+ * Sets the override attribute of the given window.
+ * @param   window            The given window.
+ * @param   override_redirect The override_redirect boolean.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_override_set(Ecore_X_Window window,
+                            int            override_redirect)
+{
+   uint32_t value_list;
+
+   value_list = override_redirect;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_OVERRIDE_REDIRECT, &value_list);
+}
+
+/**
+ * Shows the cursor of the given window.
+ * @param   window The given window.
+ * @param   show   If set to @c 0, hide the cursor. Show it otherwise.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_cursor_show(Ecore_X_Window window,
+                           int            show)
+{
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   if (!show)
+     {
+        Ecore_X_Cursor   cursor;
+        Ecore_X_Drawable draw;
+        Ecore_X_Pixmap   pixmap;
+        Ecore_X_Pixmap   mask;
+        Ecore_X_GC       gc;
+        xcb_point_t      point;
+        uint32_t         value_list;
+
+        draw = window;
+        pixmap = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_pixmap(_ecore_xcb_conn,
+                          1, pixmap, draw,
+                          1, 1);
+        mask = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_pixmap(_ecore_xcb_conn,
+                          1, mask, draw,
+                          1, 1);
+
+        gc = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL);
+        value_list = 0;
+        xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &value_list);
+
+        draw = mask;
+        point.x = 0;
+        point.y = 0;
+        xcb_poly_point(_ecore_xcb_conn, XCB_COORD_MODE_ORIGIN, draw,
+                       gc, 1, &point);
+
+        xcb_free_gc(_ecore_xcb_conn, gc);
+
+        cursor = xcb_generate_id(_ecore_xcb_conn);
+        xcb_create_cursor(_ecore_xcb_conn, cursor,
+                          pixmap, mask,
+                          0, 0, 0,
+                          0, 0, 0,
+                          0, 0);
+        value_list = cursor;
+        xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                     XCB_CW_CURSOR, &value_list);
+
+        xcb_free_cursor(_ecore_xcb_conn, cursor);
+        xcb_free_pixmap(_ecore_xcb_conn, mask);
+        xcb_free_pixmap(_ecore_xcb_conn, pixmap);
+     }
+   else
+     {
+        uint32_t value_list;
+
+        value_list = 0;
+        xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                     XCB_CW_CURSOR, &value_list);
+     }
+}
+
+/**
+ * Sets the cursor of the given window.
+ * @param   window The given window.
+ * @param   cursor The given cursor.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_cursor_set(Ecore_X_Window window,
+                          Ecore_X_Cursor cursor)
+{
+   uint32_t value_list;
+
+   value_list = cursor;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_CURSOR, &value_list);
+}
+
+/**
+ * Todo
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_container_manage(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   value_list =
+     XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_EVENT_MASK, &value_list);
+
+}
+
+/**
+ * Todo
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_client_manage(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   value_list =
+     XCB_EVENT_MASK_VISIBILITY_CHANGE |
+/*      XCB_EVENT_MASK_RESIZE_REDIRECT | */
+     XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE |
+     XCB_EVENT_MASK_PROPERTY_CHANGE |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_EVENT_MASK, &value_list);
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_select_input(_ecore_xcb_conn, window, 1);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+/**
+ * Todo
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_sniff(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   value_list =
+     XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_PROPERTY_CHANGE;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_EVENT_MASK, &value_list);
+}
+
+/**
+ * Todo
+ * @param   window The given window.
+ * @ingroup Ecore_X_Window_Change_Attributes_Group
+ */
+EAPI void
+ecore_x_window_client_sniff(Ecore_X_Window window)
+{
+   uint32_t value_list;
+
+   value_list =
+     XCB_EVENT_MASK_VISIBILITY_CHANGE |
+     XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE |
+     XCB_EVENT_MASK_PROPERTY_CHANGE |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   xcb_change_window_attributes(_ecore_xcb_conn, window,
+                                XCB_CW_EVENT_MASK, &value_list);
+#ifdef ECORE_XCB_SHAPE
+   xcb_shape_select_input(_ecore_xcb_conn, window, 1);
+#endif /* ECORE_XCB_SHAPE */
+}
+
+/**
+ * Clears an area of the given window.
+ * @param   window  The given window.
+ * @param   x            The X coordinate of the area.
+ * @param   y            The Y coordinate of the area.
+ * @param   width        The width of the area.
+ * @param   height       The height of the area.
+ * @ingroup Ecore_X_Window_Clear_Area_Group
+ */
+EAPI void
+ecore_x_window_area_clear(Ecore_X_Window window,
+                          int            x,
+                          int            y,
+                          int            width,
+                          int            height)
+{
+   xcb_clear_area(_ecore_xcb_conn, 0, window, x, y, width, height);
+}
+
+/**
+ * Exposes an area of the given window.
+ * @param   window  The given window.
+ * @param   x            The X coordinate of the area.
+ * @param   y            The Y coordinate of the area.
+ * @param   width        The width of the area.
+ * @param   height       The height of the area.
+ * @ingroup Ecore_X_Window_Clear_Area_Group
+ */
+EAPI void
+ecore_x_window_area_expose(Ecore_X_Window window,
+                           int            x,
+                           int            y,
+                           int            width,
+                           int            height)
+{
+   xcb_clear_area(_ecore_xcb_conn, 1, window, x, y, width, height);
+}
+
+
+/**
+ * @defgroup Ecore_X_Window_Save_Set_Group X Window Change Save Set Functions
+ *
+ * Functions that either inserts or deletes the specified window from
+ * the client's save-set.
+ */
+
+/**
+ * Inserts the window in the client's save-set.
+ * @param   window The window to insert in the client's save-set.
+ * @ingroup Ecore_X_Window_Save_Set_Group
+ */
+EAPI void
+ecore_x_window_save_set_add(Ecore_X_Window window)
+{
+   xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_INSERT, window);
+}
+
+/**
+ * Deletes the window from the client's save-set.
+ * @param   window The window to delete from the client's save-set.
+ * @ingroup Ecore_X_Window_Save_Set_Group
+ */
+EAPI void
+ecore_x_window_save_set_del(Ecore_X_Window window)
+{
+   xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_DELETE, window);
+}
+
+/******************************
+ *
+ * Request that have a reply
+ *
+ ******************************/
+
+
+/**
+ * Sends the GetInputFocus request.
+ * @ingroup Ecore_X_Window_Input_Focus_Group
+ */
+EAPI void
+ecore_x_get_input_focus_prefetch(void)
+{
+   xcb_get_input_focus_cookie_t cookie;
+
+   cookie = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetInputFocus request sent by ecore_x_get_input_focus_prefetch().
+ * @ingroup Ecore_X_Window_Input_Focus_Group
+ */
+EAPI void
+ecore_x_get_input_focus_fetch(void)
+{
+   xcb_get_input_focus_cookie_t cookie;
+   xcb_get_input_focus_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Gets the window that has focus.
+ * @return  The window that has focus.
+ *
+ * Returns the window that has the focus. If an error aoocured, @c 0
+ * is returned, otherwise the function returns the window that has focus.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_input_focus_prefetch(), which sends the GetInputFocus request,
+ * then ecore_x_get_input_focus_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Input_Focus_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_focus_get(void)
+{
+   xcb_get_input_focus_reply_t *reply;
+   Ecore_X_Window               window = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return window;
+
+   return reply->focus;
+}
+
+
+/**
+ * @defgroup Ecore_X_Window_Get_Attributes_Group X Window Get Attributes Functions
+ *
+ * Functions that get the attributes of a window.
+ */
+
+
+/**
+ * Sends the GetWindowAttributes request.
+ * @ingroup Ecore_X_Window_Get_Attributes_Group
+ */
+EAPI void
+ecore_x_get_window_attributes_prefetch(Ecore_X_Window window)
+{
+   xcb_get_window_attributes_cookie_t cookie;
+
+   cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the GetWindowAttributes request sent by ecore_x_get_window_attributes_prefetch().
+ * @ingroup Ecore_X_Window_Get_Attributes_Group
+ */
+EAPI void
+ecore_x_get_window_attributes_fetch(void)
+{
+   xcb_get_window_attributes_cookie_t cookie;
+   xcb_get_window_attributes_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieves the attributes of a window.
+ * @param windows Unused.
+ * @param att_ret Pointer to an Ecore_X_Window_Attributes
+ *                  structure in which the attributes of a window
+ *                  are to be stored.
+ *
+ * Retrieves the attributes of a window. If
+ * @p att_ret is @c NULL, the function does nothing. If an error
+ * occurred, @p att_ret is set to 0. Otherwise, the @p att_ret structure
+ * is filled with the attributes os the requested window.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request,
+ * then ecore_x_get_window_attributes_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Get_Attributes_Group
+ */
+EAPI int
+ecore_x_window_attributes_get(Ecore_X_Window             window __UNUSED__,
+                              Ecore_X_Window_Attributes *att_ret)
+{
+   xcb_get_window_attributes_reply_t *reply;
+
+   if (!att_ret) return 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
+
+   if (reply->map_state != XCB_MAP_STATE_UNMAPPED) att_ret->visible = 1;
+   if (reply->map_state == XCB_MAP_STATE_VIEWABLE) att_ret->viewable = 1;
+   if (reply->override_redirect) att_ret->override = 1;
+   if (reply->_class == XCB_WINDOW_CLASS_INPUT_ONLY) att_ret->input_only = 1;
+   if (reply->save_under) att_ret->save_under = 1;
+
+   att_ret->event_mask.mine         = reply->your_event_mask;
+   att_ret->event_mask.all          = reply->all_event_masks;
+   att_ret->event_mask.no_propagate = reply->do_not_propagate_mask;
+   att_ret->window_gravity          = reply->win_gravity;
+   att_ret->pixel_gravity           = reply->bit_gravity;
+   att_ret->colormap                = reply->colormap;
+   att_ret->visual                  = reply->visual;
+
+   return 1;
+}
+
+/**
+ * Finds out whether the given window is currently visible.
+ * @param  window Unused.
+ * @return        1 if the window is visible, otherwise 0.
+ *
+ * Finds out whether the given window is currently visible.
+ * If an error occurred, or if the window is not visible, 0 is
+ * returned. Otherwise 1 is returned.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request,
+ * then ecore_x_get_window_attributes_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Get_Attributes_Group
+ */
+EAPI int
+ecore_x_window_visible_get(Ecore_X_Window window __UNUSED__)
+{
+   xcb_get_window_attributes_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   return (reply->map_state == XCB_MAP_STATE_VIEWABLE) ? 1 : 0;
+}
+
+
+/**
+ * Sends the QueryPointer request.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_pointer_xy_get_prefetch(Ecore_X_Window window)
+{
+   xcb_query_pointer_cookie_t cookie;
+
+   cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, window);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the QueryPointer request sent by ecore_x_query_pointer_prefetch().
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_pointer_xy_get_fetch(void)
+{
+   xcb_query_pointer_cookie_t cookie;
+   xcb_query_pointer_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieves the coordinates of the pointer.
+ * @param window Unused.
+ * @param x      The X coordinate of the pointer.
+ * @param y      The Y coordinate of the pointer.
+ *
+ * Retrieves the coordinates of the pointer.
+ * If the window used in
+ * ecore_x_query_pointer_prefetch() is not on the same screen than
+ * the root window or if an error occured, @p x and @p y  are set
+ * to 0. Otherwise, they are respectively set to the X and Y
+ * coordinates of the pointer.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_query_pointer_prefetch(), which sends the QueryPointer request,
+ * then ecore_x_query_pointer_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_pointer_xy_get(Ecore_X_Window window __UNUSED__,
+                       int           *x,
+                       int           *y)
+{
+   xcb_query_pointer_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     {
+       if (x) *x = 0;
+       if (y) *y = 0;
+
+       return;
+     }
+
+   if (x) *x = reply->win_x;
+   if (y) *y = reply->win_y;
+}
+
+
+/**
+ * Sends the QueryTree request.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_query_tree_prefetch(Ecore_X_Window window)
+{
+   xcb_query_tree_cookie_t cookie;
+
+   cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+/**
+ * Gets the reply of the QueryTree request sent by ecore_x_query_tree_prefetch().
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_query_tree_fetch(void)
+{
+   xcb_query_tree_cookie_t cookie;
+   xcb_query_tree_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Retrieves the parent window of the given window.
+ * @param   window Unused.
+ * @return         The parent window of @p window.
+ *
+ * Retrieves the parent window of the given window. If
+ * an error occured, @c 0 is returned.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_query_tree_prefetch(), which sends the QueryTree request,
+ * then ecore_x_query_tree_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_parent_get(Ecore_X_Window window __UNUSED__)
+{
+   xcb_query_tree_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   return reply->parent;
+}
+
+
+/**
+ * Retrieves the children windows of the given window.
+ * @param   window Unused.
+ * @param   num    children windows count.
+ * @return         The children windows.
+ *
+ * Retrieves the children windows of the given window. If
+ * an error occured, @c 0 is returned.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_query_tree_prefetch(), which sends the QueryTree request,
+ * then ecore_x_query_tree_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI Ecore_X_Window *
+ecore_x_window_children_get(Ecore_X_Window window __UNUSED__,
+                            int           *num)
+{
+   xcb_query_tree_reply_t *reply;
+   Ecore_X_Window         *windows = NULL;
+
+   if (num) *num = 0;
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return NULL;
+
+   windows = malloc(sizeof(Ecore_X_Window) * reply->children_len);
+   if (!windows)
+     return NULL;
+
+   if (num) *num = reply->children_len;
+   memcpy(windows,
+          xcb_query_tree_children(reply),
+          sizeof(Ecore_X_Window) * reply->children_len);
+
+   return windows;
+}
+
+/* FIXME: I've tried to remove the round trips. 3 cookies are */
+/*        created at the beginning of the function. Because of */
+/*        the recursivity of the algo, I can't find better trick */
+static Ecore_X_Window
+_ecore_x_window_at_xy_get(Ecore_X_Window  base,
+                          int16_t         base_x,
+                          int16_t         base_y,
+                          int16_t         x,
+                          int16_t         y,
+                          Ecore_X_Window *skip,
+                          int             skip_num)
+{
+   xcb_window_iterator_t              iter_children;
+   xcb_get_window_attributes_cookie_t cookie_get_window_attributes;
+   xcb_get_geometry_cookie_t          cookie_get_geometry;
+   xcb_query_tree_cookie_t            cookie_query_tree;
+   xcb_get_window_attributes_reply_t *reply_get_window_attributes;
+   xcb_get_geometry_reply_t          *reply_get_geometry;
+   xcb_query_tree_reply_t            *reply_query_tree;
+   Ecore_X_Window                     window = 0;
+   Ecore_X_Window                     child = 0;
+   int16_t                            win_x;
+   int16_t                            win_y;
+   uint16_t                           win_width;
+   uint16_t                           win_height;
+
+   cookie_get_window_attributes = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, base);
+   cookie_get_geometry = xcb_get_geometry_unchecked(_ecore_xcb_conn, base);
+   cookie_query_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, base);
+
+   reply_get_window_attributes = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_get_window_attributes, NULL);
+   if (!reply_get_window_attributes)
+     {
+       reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
+       if (reply_get_geometry) free(reply_get_geometry);
+       reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
+       if (reply_query_tree) free(reply_query_tree);
+       return window;
+     }
+
+   if (reply_get_window_attributes->map_state != XCB_MAP_STATE_VIEWABLE)
+     {
+       free(reply_get_window_attributes);
+       reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
+       if (reply_get_geometry) free(reply_get_geometry);
+       reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
+       if (reply_query_tree) free(reply_query_tree);
+       return window;
+     }
+
+   free(reply_get_window_attributes);
+
+   reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL);
+   if (!reply_get_geometry)
+     {
+       reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
+       if (reply_query_tree) free(reply_query_tree);
+       return window;
+     }
+
+   win_x = reply_get_geometry->x;
+   win_y = reply_get_geometry->y;
+   win_width = reply_get_geometry->width;
+   win_height = reply_get_geometry->height;
+
+   free(reply_get_geometry);
+
+   win_x += base_x;
+   win_y += base_y;
+
+   if (!((x >= win_x) &&
+         (y >= win_y) &&
+         (x < (int16_t)(win_x + win_width)) &&
+         (y < (int16_t)(win_y + win_height))))
+     {
+       reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
+       if (reply_query_tree) free(reply_query_tree);
+       return window;
+     }
+
+   reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL);
+   if (!reply_query_tree)
+     {
+        if (skip)
+         {
+             int i;
+
+            for (i = 0; i < skip_num; i++)
+              if (base == skip[i])
+                return window;
+         }
+       return base;
+     }
+
+   iter_children = xcb_query_tree_children_iterator(reply_query_tree);
+   for (; iter_children.rem; xcb_window_next(&iter_children))
+     {
+        if (skip)
+          {
+             int j;
+
+             for (j = 0; j < skip_num; j++)
+               if (*iter_children.data == skip[j])
+                 continue;
+          }
+        child = _ecore_x_window_at_xy_get(*iter_children.data, win_x, win_y, x, y, skip, skip_num);
+        if (child)
+          {
+             free(reply_query_tree);
+
+             return child;
+          }
+     }
+
+   if (skip)
+     {
+        int i;
+
+       for (i = 0; i < skip_num; i++)
+         if (base == skip[i])
+            {
+               /* We return 0. child has an xid equal to 0 */
+               free(reply_query_tree);
+               return child;
+            }
+     }
+
+   free(reply_query_tree);
+
+   return base;
+}
+
+/**
+ * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
+ *
+ * Functions that change or retrieve the geometry of X windows.
+ */
+
+/**
+ * Retrieves the top, visible window at the given location.
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return    The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_get(int x,
+                           int y)
+{
+   Ecore_X_Window window;
+   Ecore_X_Window root;
+
+   /* FIXME: Proper function to determine current root/virtual root
+    * window missing here */
+   root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ecore_x_grab();
+   window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
+   ecore_x_ungrab();
+
+   return window ? window : root;
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but skips the windows in the list.
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return    The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_with_skip_get(int             x,
+                                     int             y,
+                                     Ecore_X_Window *skip,
+                                     int             skip_num)
+{
+   Ecore_X_Window window;
+   Ecore_X_Window root;
+
+   /* FIXME: Proper function to determine current root/virtual root
+    * window missing here */
+   root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ecore_x_grab();
+   window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
+   ecore_x_ungrab();
+
+   return window ? window : root;
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but begins at the @p begin window instead of the root one.
+ * @param   begin The window from which we begin.
+ * @param   x     The given X position.
+ * @param   y     The given Y position.
+ * @return        The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_begin_get(Ecore_X_Window begin,
+                               int            x,
+                               int            y)
+{
+   Ecore_X_Window window;
+
+   ecore_x_grab();
+   window = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
+   ecore_x_ungrab();
+
+   return window ? window : begin;
+}
+
+
+
+/* FIXME: Should I provide the replies (or the cookies), instead of
+          creating them in the function ? */
+#ifdef ECORE_XCB_RENDER
+static Ecore_X_Window
+_ecore_x_window_argb_internal_new(Ecore_X_Window parent,
+                                  int16_t        x,
+                                  int16_t        y,
+                                  uint16_t       w,
+                                  uint16_t       h,
+                                  uint8_t        override_redirect,
+                                  uint8_t        save_under)
+{
+   uint32_t                               value_list[10];
+   xcb_depth_iterator_t                   iter_depth;
+   xcb_visualtype_iterator_t              iter_visualtype;
+   xcb_render_query_pict_formats_cookie_t cookie_pict_format;
+   xcb_render_query_pict_formats_reply_t *rep_pict_format;
+   Ecore_X_Screen                        *screen = NULL;
+   Ecore_X_Window                         win = { 0 };
+   xcb_visualid_t                         vis = { 0 };
+   Ecore_X_Colormap                       colormap;
+   uint32_t                               value_mask;
+
+   cookie_pict_format = xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn);
+
+   if (parent == 0)
+     {
+        parent = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+       screen = ((xcb_screen_t *)_ecore_xcb_screen);
+     }
+   else
+     {
+        xcb_screen_iterator_t     iter_screen;
+        xcb_get_geometry_reply_t *rep;
+        Ecore_X_Drawable        draw;
+        Ecore_X_Window          root;
+
+        draw = parent;
+        rep = xcb_get_geometry_reply(_ecore_xcb_conn,
+                                     xcb_get_geometry_unchecked(_ecore_xcb_conn,
+                                                                draw),
+                                     NULL);
+        if (!rep)
+          return win;
+
+        root = rep->root;
+
+        free(rep);
+
+        for (; iter_screen.rem; xcb_screen_next(&iter_screen))
+          {
+             if (iter_screen.data->root == root)
+               {
+                 screen = iter_screen.data;
+               }
+          }
+     }
+   if (!screen)
+     return win;
+
+   /* we get the X visual types */
+   iter_depth = xcb_screen_allowed_depths_iterator(screen);
+   for (; iter_depth.rem; xcb_depth_next(&iter_depth)) {
+       if (iter_depth.data->depth == 32) {
+            iter_visualtype = xcb_depth_visuals_iterator(iter_depth.data);
+            break;
+       }
+   }
+
+   /* we get the X render visual id */
+   rep_pict_format = xcb_render_query_pict_formats_reply(_ecore_xcb_conn,
+                                                         cookie_pict_format,
+                                                         NULL);
+   if (!rep_pict_format)
+     return win;
+
+   for (; iter_visualtype.rem; xcb_visualtype_next(&iter_visualtype)) {
+      if (iter_visualtype.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) {
+         xcb_render_pictforminfo_iterator_t iter_forminfo;
+         xcb_render_pictscreen_iterator_t   iter_pictscreen;
+         xcb_render_pictformat_t            pict_format = { 0 };
+
+         iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pict_format);
+         for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo)) {
+            if (iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT &&
+                iter_forminfo.data->direct.alpha_mask && iter_forminfo.data->depth == 32) {
+               pict_format = iter_forminfo.data->id;
+               break;
+            }
+         }
+         if (pict_format == 0) {
+            free(rep_pict_format);
+            return win;
+         }
+         iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pict_format);
+         for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen)) {
+            xcb_render_pictdepth_iterator_t iter_depth;
+
+            iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data);
+            for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth)) {
+               xcb_render_pictvisual_iterator_t iter_visual;
+
+               iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data);
+               for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual)) {
+                  if ((iter_visual.data->visual == iter_visualtype.data->visual_id) &&
+                      (pict_format == iter_visual.data->format)) {
+                    vis = iter_visual.data->visual;
+                    break;
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   free(rep_pict_format);
+
+   if (vis == 0)
+     return win;
+
+   colormap = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_colormap(_ecore_xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, parent, vis);
+
+   value_mask =
+     XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL  | XCB_CW_BIT_GRAVITY       |
+     XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT |
+     XCB_CW_SAVE_UNDER  | XCB_CW_EVENT_MASK    | XCB_CW_DONT_PROPAGATE    |
+     XCB_CW_COLORMAP;
+
+   value_list[0]  = XCB_NONE;
+   value_list[1]  = 0;
+   value_list[2]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[3]  = XCB_GRAVITY_NORTH_WEST;
+   value_list[4]  = XCB_BACKING_STORE_NOT_USEFUL;
+   value_list[5]  = override_redirect;
+   value_list[6]  = save_under;
+   value_list[7]  =
+     XCB_EVENT_MASK_KEY_PRESS         | XCB_EVENT_MASK_KEY_RELEASE      |
+     XCB_EVENT_MASK_BUTTON_PRESS      | XCB_EVENT_MASK_BUTTON_RELEASE   |
+     XCB_EVENT_MASK_ENTER_WINDOW      | XCB_EVENT_MASK_LEAVE_WINDOW     |
+     XCB_EVENT_MASK_POINTER_MOTION    | XCB_EVENT_MASK_EXPOSURE        |
+     XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+     XCB_EVENT_MASK_FOCUS_CHANGE      | XCB_EVENT_MASK_PROPERTY_CHANGE  |
+     XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+   value_list[8]  = XCB_EVENT_MASK_NO_EVENT;
+   value_list[9]  = colormap;
+
+   win = xcb_generate_id(_ecore_xcb_conn);
+   xcb_create_window(_ecore_xcb_conn,
+                     32, /* depth */
+                     win, parent,
+                     x, y, w, h, 0,
+                     XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                     vis,
+                     value_mask,
+                     value_list);
+
+   xcb_free_colormap(_ecore_xcb_conn, colormap);
+
+   if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root)
+     ecore_x_window_defaults_set(win);
+
+   return win;
+}
+#endif /* ECORE_XCB_RENDER */
+
+
+
+/* FIXME: round trip */
+EAPI int
+ecore_x_window_argb_get(Ecore_X_Window win)
+{
+   uint8_t                                ret = 0;
+#ifdef ECORE_XCB_RENDER
+   xcb_render_pictforminfo_iterator_t     iter_forminfo;
+   xcb_render_pictscreen_iterator_t       iter_pictscreen;
+   xcb_render_pictformat_t                pict_format = { 0 };
+   xcb_render_query_pict_formats_reply_t *rep_pictformat;
+   xcb_get_window_attributes_reply_t     *rep;
+   xcb_visualid_t                         visual;
+
+   rep = xcb_get_window_attributes_reply(_ecore_xcb_conn,
+                                         xcb_get_window_attributes_unchecked(_ecore_xcb_conn,
+                                                                             win),
+                                         NULL);
+   if (!rep)
+     return ret;
+
+   visual = rep->visual;
+
+   free(rep);
+
+   rep_pictformat = xcb_render_query_pict_formats_reply(_ecore_xcb_conn,
+                                                        xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn),
+                                                        NULL);
+   if (!rep_pictformat)
+     return ret;
+
+   iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pictformat);
+   for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo))
+     {
+        if ((iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT) &&
+            (iter_forminfo.data->direct.alpha_mask))
+          {
+             pict_format = iter_forminfo.data->id;
+             break;
+          }
+     }
+   if (pict_format == 0)
+     {
+        free(rep_pictformat);
+
+        return ret;
+     }
+
+   iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pictformat);
+   for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen))
+     {
+        xcb_render_pictdepth_iterator_t iter_depth;
+
+        iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data);
+        for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth))
+          {
+             xcb_render_pictvisual_iterator_t iter_visual;
+
+             iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data);
+             for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual))
+               {
+                  if ((iter_visual.data->visual == visual) &&
+                      (pict_format == iter_visual.data->format))
+                    {
+                       ret = 1;
+                       break;
+                    }
+               }
+          }
+     }
+
+   free(rep_pictformat);
+#endif /* ECORE_XCB_RENDER */
+
+   return ret;
+}
+
+
+
+
+/**
+ * Set if a window should be ignored.
+ * @param   window The given window.
+ * @param   ignore if to ignore
+ */
+EAPI void
+ecore_x_window_ignore_set(Ecore_X_Window window,
+                          int            ignore)
+{
+   int i, j;
+
+   if (ignore)
+     {
+       if (ignore_list)
+         {
+            for (i = 0; i < ignore_num; i++)
+              {
+                 if (window == ignore_list[i])
+                   return;
+              }
+            ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
+            if (!ignore_list) return;
+            ignore_list[ignore_num++] = window;
+         }
+       else
+         {
+            ignore_num = 0;
+            ignore_list = malloc(sizeof(Ecore_X_Window));
+            ignore_list[ignore_num++] = window;
+         }
+     }
+   else
+     {
+       if (!ignore_list) return;
+       for (i = 0, j = 0; i < ignore_num; i++)
+         {
+            if (window != ignore_list[i])
+              ignore_list[i] = ignore_list[j++];
+            else
+              ignore_num--;
+         }
+       ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
+     }
+}
+
+/**
+ * Get the ignore list
+ * @param   num number of windows in the list
+ * @return  list of windows to ignore
+ */
+EAPI Ecore_X_Window *
+ecore_x_window_ignore_list(int *num)
+{
+   if (num) *num = ignore_num;
+   return ignore_list;
+}
+
+/**
+ * Retrieves the size of the given window.
+ * @param   win The given window.
+ * @param   w   Pointer to an integer into which the width is to be stored.
+ * @param   h   Pointer to an integer into which the height is to be stored.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
+ * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_size_get(Ecore_X_Window window,
+                        int           *width,
+                        int           *height)
+{
+   if (window == 0)
+      window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ecore_x_drawable_geometry_get(window, NULL, NULL, width, height);
+}
+
+/**
+ * Retrieves the geometry of the given window.
+ * @param   win The given window.
+ * @param   x   Pointer to an integer in which the X position is to be stored.
+ * @param   y   Pointer to an integer in which the Y position is to be stored.
+ * @param   w   Pointer to an integer in which the width is to be stored.
+ * @param   h   Pointer to an integer in which the height is to be stored.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request,
+ * then ecore_x_drawable_geometry_get_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_geometry_get(Ecore_X_Window window,
+                            int           *x,
+                            int           *y,
+                            int           *width,
+                            int           *height)
+{
+   if (!window)
+      window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+
+   ecore_x_drawable_geometry_get(window, x, y, width, height);
+}
+
+/**
+ * Retrieves the width of the border of the given window.
+ * @param   win The given window.
+ * @return  Width of the border of @p win.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI int
+ecore_x_window_border_width_get(Ecore_X_Window win)
+{
+   /* doesn't make sense to call this on a root window */
+   if (!win)
+      return 0;
+
+   return ecore_x_drawable_border_width_get(win);
+}
+
+/**
+ * Retrieves the depth of the given window.
+ * @param  win The given window.
+ * @return Depth of the window.
+ */
+EAPI int
+ecore_x_window_depth_get(Ecore_X_Window win)
+{
+   return ecore_x_drawable_depth_get(win);
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c b/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c
new file mode 100644 (file)
index 0000000..3fc3d17
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ecore_xcb_private.h"
+#include "Ecore_X_Atoms.h"
+
+
+/*
+ * Set CARD32 (array) property
+ */
+EAPI void
+ecore_x_window_prop_card32_set(Ecore_X_Window win,
+                               Ecore_X_Atom   atom,
+                              unsigned int  *val,
+                               unsigned int   num)
+{
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
+                       atom, ECORE_X_ATOM_CARDINAL, 32, num, (const void *)val);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @param atom   The atom.
+ */
+EAPI void
+ecore_x_window_prop_card32_get_prefetch(Ecore_X_Window window,
+                                        Ecore_X_Atom atom)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window,
+                                       atom,
+                                       ECORE_X_ATOM_CARDINAL,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_card32_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_card32_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * Get CARD32 (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_card32_get(Ecore_X_Window win __UNUSED__,
+                               Ecore_X_Atom   atom __UNUSED__,
+                              unsigned int  *val,
+                               unsigned int   len)
+{
+   xcb_get_property_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply ||
+       (reply->type != ECORE_X_ATOM_CARDINAL) ||
+       (reply->format != 32))
+      return -1;
+
+   if (reply->value_len < len)
+     len = xcb_get_property_value_length(reply);
+
+   if (val)
+      memcpy(val, xcb_get_property_value(reply), len);
+
+   return (int)len;
+}
+
+/*
+ * Get CARD32 (array) property of any length
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_card32_list_get(Ecore_X_Window win __UNUSED__,
+                                    Ecore_X_Atom   atom __UNUSED__,
+                                   unsigned int **plist)
+{
+   xcb_get_property_reply_t *reply;
+   int                       num = -1;
+
+   if (plist)
+      *plist = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return -1;
+
+   if ((reply->type == XCB_NONE) ||
+       (reply->value_len == 0))
+      num = 0;
+   else if ((reply->type == ECORE_X_ATOM_CARDINAL) &&
+            (reply->format == 32))
+     {
+       uint32_t *val;
+
+       num = xcb_get_property_value_length(reply);
+       if (plist)
+         {
+            val = (uint32_t *)malloc (num);
+            if (!val)
+               goto error;
+
+            memcpy(val, xcb_get_property_value(reply), num);
+            *plist = val;
+         }
+     }
+
+ error:
+
+   return num;
+}
+
+/*
+ * Set X ID (array) property
+ */
+EAPI void
+ecore_x_window_prop_xid_set(Ecore_X_Window win,
+                            Ecore_X_Atom   atom,
+                           Ecore_X_Atom   type,
+                            Ecore_X_ID    *xids,
+                           unsigned int   num)
+{
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
+                       atom, type, 32, num, xids);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @param atom   The atom.
+ * @param type   The atom type.
+ */
+EAPI void
+ecore_x_window_prop_xid_get_prefetch(Ecore_X_Window window,
+                                     Ecore_X_Atom   atom,
+                                     Ecore_X_Atom   type)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window,
+                                       atom,
+                                       type,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_xid_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_xid_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * Get X ID (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_xid_get(Ecore_X_Window win __UNUSED__,
+                            Ecore_X_Atom   atom __UNUSED__,
+                           Ecore_X_Atom   type __UNUSED__,
+                            Ecore_X_ID    *xids,
+                           unsigned int   len)
+{
+   xcb_get_property_reply_t *reply;
+   int                       num = len;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return -1;
+
+   if (reply->type == XCB_NONE)
+      num = 0;
+   else if (reply->format == 32)
+     {
+        if (reply->value_len < len)
+          num = xcb_get_property_value_length(reply);
+
+        if (xids)
+           memcpy(xids, xcb_get_property_value(reply), num);
+     }
+
+   return num;
+}
+
+/*
+ * Get X ID (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_xid_list_get(Ecore_X_Window win __UNUSED__,
+                                 Ecore_X_Atom   atom __UNUSED__,
+                                Ecore_X_Atom   type __UNUSED__,
+                                 Ecore_X_ID   **pxids)
+{
+   xcb_get_property_reply_t *reply;
+   int                       num = -1;
+
+   if (pxids)
+      *pxids = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return -1;
+
+   if ((reply->type == XCB_NONE) ||
+       (reply->value_len == 0))
+      num = 0;
+   else if ((reply->type == ECORE_X_ATOM_CARDINAL) &&
+            (reply->format == 32))
+     {
+       uint32_t *val;
+
+       num = xcb_get_property_value_length(reply);
+       if (pxids)
+         {
+            val = (uint32_t *)malloc (num);
+            if (!val)
+               return -1;
+
+            memcpy(val, xcb_get_property_value(reply), num);
+            *pxids = val;
+         }
+     }
+
+   return num;
+}
+
+/*
+ * Remove/add/toggle X ID list item.
+ */
+EAPI void
+ecore_x_window_prop_xid_list_change(Ecore_X_Window win,
+                                    Ecore_X_Atom   atom,
+                                    Ecore_X_Atom   type,
+                                    Ecore_X_ID     item,
+                                    int            op)
+{
+   Ecore_X_ID *lst;
+   int         i;
+   int         num;
+
+   num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst);
+   if (num < 0)
+      return;                  /* Error - assuming invalid window */
+
+   /* Is it there? */
+   for (i = 0; i < num; i++)
+     {
+       if (lst[i] == item)
+          break;
+     }
+
+   if (i < num)
+     {
+       /* Was in list */
+       if (op == ECORE_X_PROP_LIST_ADD)
+          goto done;
+       /* Remove it */
+       num--;
+       for (; i < num; i++)
+          lst[i] = lst[i + 1];
+     }
+   else
+     {
+       /* Was not in list */
+       if (op == ECORE_X_PROP_LIST_REMOVE)
+          goto done;
+       /* Add it */
+       num++;
+       lst = realloc(lst, num * sizeof(Ecore_X_ID));
+       lst[i] = item;
+     }
+
+   ecore_x_window_prop_xid_set(win, atom, type, lst, num);
+
+ done:
+   if (lst)
+      free(lst);
+}
+
+/*
+ * Set Atom (array) property
+ */
+EAPI void
+ecore_x_window_prop_atom_set(Ecore_X_Window win,
+                             Ecore_X_Atom   atom,
+                             Ecore_X_Atom  *list,
+                             unsigned int   num)
+{
+   ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_ATOM, list, num);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @param atom   Property atom.
+ */
+EAPI void
+ecore_x_window_prop_atom_get_prefetch(Ecore_X_Window window,
+                                      Ecore_X_Atom   atom)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window,
+                                       atom,
+                                       ECORE_X_ATOM_ATOM,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_atom_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_atom_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * Get Atom (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_atom_get(Ecore_X_Window win,
+                             Ecore_X_Atom   atom,
+                             Ecore_X_Atom  *list,
+                             unsigned int len)
+{
+   return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_ATOM, list, len);
+}
+
+/*
+ * Get Atom (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_atom_list_get(Ecore_X_Window win,
+                                  Ecore_X_Atom   atom,
+                                  Ecore_X_Atom **plist)
+{
+   return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_ATOM, plist);
+}
+
+/*
+ * Remove/add/toggle atom list item.
+ */
+EAPI void
+ecore_x_window_prop_atom_list_change(Ecore_X_Window win,
+                                     Ecore_X_Atom   atom,
+                                     Ecore_X_Atom   item,
+                                     int            op)
+{
+   ecore_x_window_prop_xid_list_change(win, atom, ECORE_X_ATOM_ATOM, item, op);
+}
+
+/*
+ * Set Window (array) property
+ */
+EAPI void
+ecore_x_window_prop_window_set(Ecore_X_Window  win,
+                               Ecore_X_Atom    atom,
+                               Ecore_X_Window *list,
+                               unsigned int    num)
+{
+   ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_WINDOW, list, num);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @param atom   The atom.
+ */
+EAPI void
+ecore_x_window_prop_window_get_prefetch(Ecore_X_Window window,
+                                        Ecore_X_Atom   atom)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window,
+                                       atom,
+                                       ECORE_X_ATOM_WINDOW,
+                                       0, 0x7fffffff);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_window_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_window_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/*
+ * Get Window (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_window_get(Ecore_X_Window  win,
+                               Ecore_X_Atom    atom,
+                               Ecore_X_Window *list,
+                               unsigned int    len)
+{
+   return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_WINDOW, list, len);
+}
+
+/*
+ * Get Window (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_window_list_get(Ecore_X_Window   win,
+                                    Ecore_X_Atom     atom,
+                                    Ecore_X_Window **plist)
+{
+   return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_WINDOW, plist);
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI Ecore_X_Atom
+ecore_x_window_prop_any_type(void)
+{
+   return XCB_GET_PROPERTY_TYPE_ANY;
+}
+
+/**
+ * To be documented.
+ * @param window   The window.
+ * @param property The property atom.
+ * @param type     The type atom.
+ * @param size     The size.
+ * @param data     The data.
+ * @param number   The size of the data.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI void
+ecore_x_window_prop_property_set(Ecore_X_Window window,
+                                 Ecore_X_Atom   property,
+                                 Ecore_X_Atom   type,
+                                 int            size,
+                                 void          *data,
+                                 int            number)
+{
+   if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
+                       property, type,
+                       size, number, data);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window   Window whose properties are requested.
+ * @param property Property atom.
+ * @param type     Type atom.
+ */
+EAPI void
+ecore_x_window_prop_property_get_prefetch(Ecore_X_Window window,
+                                          Ecore_X_Atom   property,
+                                          Ecore_X_Atom   type)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       property, type, 0, LONG_MAX);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_property_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_property_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * To be documented.
+ * @param window   The window (Unused).
+ * @param property The property atom (Unused).
+ * @param type     The type atom (Unused).
+ * @param size     The size (Unused).
+ * @param data     The returned data.
+ * @param num      The size of the data.
+ * @return         1 on success, 0 otherwise.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI int
+ecore_x_window_prop_property_get(Ecore_X_Window  window __UNUSED__,
+                                 Ecore_X_Atom    property __UNUSED__,
+                                 Ecore_X_Atom    type __UNUSED__,
+                                 int             size __UNUSED__,
+                                 unsigned char **data,
+                                 int            *num)
+{
+   xcb_get_property_reply_t *reply;
+
+   /* make sure these are initialized */
+   if (num) *num = 0L;
+
+   if (data)
+     *data = NULL;
+   else /* we can't store the retrieved data, so just return */
+     return 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return 0;
+
+   if ((reply->format != size) ||
+       (reply->value_len == 0))
+      return 0;
+
+   *data = malloc(reply->value_len);
+   if (!*data)
+      return 0;
+
+   memcpy(*data, xcb_get_property_value(reply), 
+          xcb_get_property_value_length(reply));
+
+   if (num)
+      *num = reply->value_len;
+
+   return reply->format;
+}
+
+EAPI void
+ecore_x_window_prop_property_del(Ecore_X_Window window,
+                                 Ecore_X_Atom   property)
+{
+   xcb_delete_property(_ecore_xcb_conn, window, property);
+}
+
+/**
+ * Sends the ListProperties request.
+ * @param window Window whose properties are requested.
+ */
+EAPI void
+ecore_x_window_prop_list_prefetch(Ecore_X_Window window)
+{
+   xcb_list_properties_cookie_t cookie;
+
+   cookie = xcb_list_properties_unchecked(_ecore_xcb_conn, window);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the ListProperties request sent by ecore_x_window_prop_list_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_list_fetch(void)
+{
+   xcb_list_properties_cookie_t cookie;
+   xcb_list_properties_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_list_properties_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+
+/**
+ * To be documented.
+ * @param window  The window (Unused).
+ * @param num_ret The number of atoms.
+ * @return        The returned atoms.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI Ecore_X_Atom *
+ecore_x_window_prop_list(Ecore_X_Window window __UNUSED__,
+                         int           *num_ret)
+{
+   xcb_list_properties_reply_t *reply;
+   Ecore_X_Atom                *atoms;
+
+   if (num_ret) *num_ret = 0;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+      return NULL;
+
+   atoms = (Ecore_X_Atom *)malloc(reply->atoms_len * sizeof(Ecore_X_Atom));
+   if (!atoms)
+      return NULL;
+   memcpy(atoms,
+          xcb_list_properties_atoms(reply),
+          reply->atoms_len * sizeof(Ecore_X_Atom));
+   if(num_ret)
+     *num_ret = reply->atoms_len;
+
+   return atoms;
+}
+
+/**
+ * Set a window string property.
+ * @param win The window
+ * @param type The property
+ * @param str The string
+ *
+ * Set a window string property
+ */
+EAPI void
+ecore_x_window_prop_string_set(Ecore_X_Window win,
+                               Ecore_X_Atom   type,
+                               const char    *str)
+{
+   if (win == 0) win = ((xcb_screen_t *)_ecore_xcb_screen)->root;
+   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
+                     type, ECORE_X_ATOM_UTF8_STRING,
+                     8, strlen(str), str);
+}
+
+/**
+ * Sends the GetProperty request.
+ * @param window Window whose properties are requested.
+ * @param type   The atom.
+ */
+EAPI void
+ecore_x_window_prop_string_get_prefetch(Ecore_X_Window window,
+                                        Ecore_X_Atom   type)
+{
+   xcb_get_property_cookie_t cookie;
+
+   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
+                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
+                                       type, XCB_GET_PROPERTY_TYPE_ANY, 0L, 1000000L);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+}
+
+
+/**
+ * Gets the reply of the GetProperty request sent by ecore_x_window_prop_string_get_prefetch().
+ */
+EAPI void
+ecore_x_window_prop_string_get_fetch(void)
+{
+   xcb_get_property_cookie_t cookie;
+   xcb_get_property_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+}
+
+/**
+ * Get a window string property.
+ * @param window The window
+ * @param type The property
+ *
+ * Return window string property of a window. String must be free'd when done.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_window_prop_string_get_prefetch(), which sends the GetProperty request,
+ * then ecore_x_window_prop_string_get_fetch(), which gets the reply.
+ */
+EAPI char *
+ecore_x_window_prop_string_get(Ecore_X_Window window __UNUSED__,
+                               Ecore_X_Atom   type __UNUSED__)
+{
+   xcb_get_property_reply_t *reply;
+   char                     *str = NULL;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     return NULL;
+
+   if (reply->type == ECORE_X_ATOM_UTF8_STRING)
+     {
+        int length;
+
+        length = reply->value_len;
+        str = (char *)malloc(length + 1);
+        memcpy(str,
+               xcb_get_property_value(reply),
+               length);
+        str[length] = '\0';
+     }
+   else
+     {
+       /* FIXME: to be done... */
+
+/* #ifdef X_HAVE_UTF8_STRING */
+/*         s = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xtp, */
+/*                                         &list, &items); */
+/* #else */
+/*         s = XmbTextPropertyToTextList(_ecore_xcb_conn, &xtp, */
+/*                                       &list, &items); */
+/* #endif */
+/*         if ((s == XLocaleNotSupported) || */
+/*             (s == XNoMemory) || (s == XConverterNotFound)) */
+/*           { */
+/*              str = strdup((char *)xtp.value); */
+/*           } */
+/*         else if ((s >= Success) && (items > 0)) */
+/*           { */
+/*              str = strdup(list[0]); */
+/*           } */
+/*         if (list) */
+/*            XFreeStringList(list); */
+     }
+
+   return str;
+}
+
+/* FIXME : round trips because of GetWMProtocols */
+/*         should we rewrite its code ? */
+EAPI int
+ecore_x_window_prop_protocol_isset(Ecore_X_Window      window,
+                                   Ecore_X_WM_Protocol protocol)
+{
+   xcb_get_property_cookie_t    cookie;
+   xcb_get_wm_protocols_reply_t protocols;
+   Ecore_X_Atom                 proto;
+   uint32_t                     i;
+   uint8_t                      ret = 0;
+
+   /* check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+       return ret;
+
+   proto = _ecore_xcb_atoms_wm_protocols[protocol];
+
+   cookie = xcb_get_wm_protocols(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_PROTOCOLS);
+
+   if (!xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protocols, NULL))
+     return ret;
+
+   for (i = 0; i < protocols.atoms_len; i++)
+     if (protocols.atoms[i] == proto)
+       {
+          ret = 1;
+          break;
+       }
+
+   xcb_get_wm_protocols_reply_wipe(&protocols);
+
+   return ret;
+}
+
+/**
+ * To be documented.
+ * @param window  The window.
+ * @param num_ret The number of WM protocols.
+ * @return        The returned WM protocols.
+ *
+ * FIXME: To be fixed.
+ */
+
+/* FIXME : round trips because of get_wm_protocols */
+/*         should we rewrite its code ? */
+
+EAPI Ecore_X_WM_Protocol *
+ecore_x_window_prop_protocol_list_get(Ecore_X_Window window,
+                                      int           *num_ret)
+{
+   xcb_get_property_cookie_t    cookie;
+   xcb_get_wm_protocols_reply_t protocols;
+   Ecore_X_WM_Protocol         *prot_ret = NULL;
+   uint32_t                     protos_count;
+   uint32_t                     i;
+
+   cookie = xcb_get_wm_protocols(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_PROTOCOLS);
+
+   if (!xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protocols, NULL))
+      return NULL;
+
+   if ((protocols.atoms_len <= 0)) return NULL;
+
+   prot_ret = calloc(1, protocols.atoms_len * sizeof(Ecore_X_WM_Protocol));
+   if (!prot_ret)
+     {
+       xcb_get_wm_protocols_reply_wipe(&protocols);
+       return NULL;
+     }
+   for (i = 0; i < protocols.atoms_len; i++)
+     {
+       Ecore_X_WM_Protocol j;
+
+       prot_ret[i] = -1;
+       for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++)
+         {
+            if (_ecore_xcb_atoms_wm_protocols[j] == protocols.atoms[i])
+              prot_ret[i] = j;
+         }
+     }
+   xcb_get_wm_protocols_reply_wipe(&protocols);
+   *num_ret = protos_count;
+
+   return prot_ret;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c b/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c
new file mode 100644 (file)
index 0000000..c025673
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/* #include "Ecore.h" */
+#include "ecore_xcb_private.h"
+#include "Ecore_X.h"
+
+
+typedef struct _Shadow Shadow;
+struct _Shadow
+{
+   Shadow         *parent;
+   Shadow        **children;
+   Ecore_X_Window  win;
+   int             children_num;
+   short           x, y;
+   unsigned short  w, h;
+};
+
+static int shadow_count = 0;
+static Shadow **shadow_base = NULL;
+static int shadow_num = 0;
+
+
+/* FIXME: round trips */
+static Shadow *
+_ecore_x_window_tree_walk(Ecore_X_Window window)
+{
+   Shadow                            *s;
+   Shadow                           **sl;
+   xcb_get_window_attributes_reply_t *reply_attr;
+   xcb_get_geometry_reply_t          *reply_geom;
+   xcb_query_tree_reply_t            *reply_tree;
+   xcb_get_window_attributes_cookie_t cookie_attr;
+   xcb_get_geometry_cookie_t          cookie_geom;
+   xcb_query_tree_cookie_t            cookie_tree;
+   int                                i;
+   int                                j;
+
+   cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
+   cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
+   cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
+
+   reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
+   if (!reply_attr)
+     {
+        reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+        if (reply_geom) free(reply_geom);
+        reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+        if (reply_tree) free(reply_tree);
+        return NULL;
+     }
+
+   if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE)
+     {
+        reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+        if (reply_geom) free(reply_geom);
+        reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+        if (reply_tree) free(reply_tree);
+        return NULL;
+     }
+
+   free(reply_attr);
+
+   s = calloc(1, sizeof(Shadow));
+   if (!s) return NULL;
+
+   reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
+   if (!reply_geom)
+     {
+        reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+        if (reply_tree) free(reply_tree);
+        return NULL;
+     }
+
+   s->win = window;
+   s->x = reply_geom->x;
+   s->y = reply_geom->y;
+   s->w = reply_geom->width;
+   s->h = reply_geom->height;
+
+   free(reply_geom);
+
+   reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
+   if (reply_tree)
+/*    if (XQueryTree(_ecore_xcb_conn, s->win, &root_win, &parent_win, */
+/*                &list, &num)) */
+     {
+        xcb_window_t *list;
+        int           num;
+
+        num = xcb_query_tree_children_length(reply_tree);
+        list = xcb_query_tree_children(reply_tree);
+
+       s->children = calloc(1, sizeof(Shadow *) * num);
+       if (s->children)
+         {
+            s->children_num = num;
+            for (i = 0; i < num; i++)
+              {
+                 s->children[i] = _ecore_x_window_tree_walk(list[i]);
+                 if (s->children[i]) s->children[i]->parent = s;
+              }
+            /* compress list down */
+            j = 0;
+            for (i = 0; i < num; i++)
+              {
+                 if (s->children[i])
+                   {
+                      s->children[j] = s->children[i];
+                      j++;
+                   }
+              }
+            if (j == 0)
+              {
+                 free(s->children);
+                 s->children = NULL;
+                 s->children_num = 0;
+              }
+            else
+              {
+                 s->children_num = j;
+                 sl = realloc(s->children, sizeof(Shadow *) * j);
+                 if (sl) s->children = sl;
+              }
+         }
+        free(reply_tree);
+     }
+   return s;
+}
+
+static void
+_ecore_x_window_tree_shadow_free1(Shadow *s)
+{
+   int i;
+
+   if (!s) return;
+   if (s->children)
+     {
+       for (i = 0; i < s->children_num; i++)
+         {
+            if (s->children[i])
+              _ecore_x_window_tree_shadow_free1(s->children[i]);
+         }
+       free(s->children);
+     }
+   free(s);
+}
+
+static void
+_ecore_x_window_tree_shadow_free(void)
+{
+   int i;
+
+   if (!shadow_base) return;
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       _ecore_x_window_tree_shadow_free1(shadow_base[i]);
+     }
+   free(shadow_base);
+   shadow_base = NULL;
+   shadow_num = 0;
+}
+
+static void
+_ecore_x_window_tree_shadow_populate(void)
+{
+   Ecore_X_Window   *roots;
+   int               i, num;
+
+   roots = ecore_x_window_root_list(&num);
+   if (roots)
+     {
+       shadow_base = calloc(1, sizeof(Shadow *) * num);
+       if (shadow_base)
+         {
+            shadow_num = num;
+            for (i = 0; i < num; i++)
+              shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
+         }
+       free(roots);
+     }
+}
+
+static void
+_ecore_x_window_tree_shadow_start(void)
+{
+   shadow_count++;
+   if (shadow_count > 1) return;
+   _ecore_x_window_tree_shadow_populate();
+}
+
+static void
+_ecore_x_window_tree_shadow_stop(void)
+{
+   shadow_count--;
+   if (shadow_count != 0) return;
+   _ecore_x_window_tree_shadow_free();
+}
+
+Shadow *
+_ecore_x_window_shadow_tree_find_shadow(Shadow *s, Ecore_X_Window win)
+{
+   Shadow *ss;
+   int i;
+
+   if (s->win == win) return s;
+   if (s->children)
+     {
+       for (i = 0; i < s->children_num; i++)
+         {
+            if (!s->children[i]) continue;
+            if ((ss = _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
+              return ss;
+         }
+     }
+   return NULL;
+}
+
+Shadow *
+_ecore_x_window_shadow_tree_find(Ecore_X_Window base)
+{
+   Shadow *s;
+   int i;
+
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
+         return s;
+     }
+   return NULL;
+}
+
+static Ecore_X_Window
+_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, int bx, int by, int x, int y,
+                                            Ecore_X_Window *skip, int skip_num)
+{
+   Ecore_X_Window child;
+   int i, j;
+   int wx, wy;
+
+   wx = s->x + bx;
+   wy = s->y + by;
+   if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
+     return 0;
+   if (s->children)
+     {
+       int skipit = 0;
+
+       for (i = s->children_num - 1; i >= 0; --i)
+         {
+            if (!s->children[i]) continue;
+            skipit = 0;
+            if (skip)
+              {
+                 for (j = 0; j < skip_num; j++)
+                   {
+                      if (s->children[i]->win == skip[j])
+                        {
+                           skipit = 1;
+                           goto onward;
+                        }
+                   }
+              }
+            onward:
+            if (!skipit)
+              {
+                 if ((child = _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num)))
+                   {
+                      return child;
+                   }
+              }
+         }
+     }
+   return s->win;
+}
+
+static Ecore_X_Window
+_ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base, int bx, int by, int x, int y,
+                                     Ecore_X_Window *skip, int skip_num)
+{
+   Shadow *s;
+
+   if (!shadow_base)
+     {
+       _ecore_x_window_tree_shadow_populate();
+       if (!shadow_base) return 0;
+     }
+   s = _ecore_x_window_shadow_tree_find(base);
+   if (!s) return 0;
+   return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num);
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but skips the windows in the list. This uses a shadow tree built from the
+ * window tree that is only updated the first time
+ * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
+ * it is called after a  ecore_x_window_shadow_tree_flush()
+ * @param   base The base window to start searching from (normally root).
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return  The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num)
+{
+   return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num);
+}
+
+/**
+ * Retrieves the parent window a given window has. This uses the shadow window
+ * tree.
+ * @param   root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
+ * @param   win The window to get the parent window of
+ * @return  The parent window of @p win
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win)
+{
+   Shadow *s;
+   int     i;
+
+   if (!shadow_base)
+     {
+       _ecore_x_window_tree_shadow_populate();
+       if (!shadow_base) return 0;
+     }
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
+       if (s)
+         {
+            if (!s->parent) return 0;
+            return s->parent->win;
+         }
+     }
+   return 0;
+}
+
+/**
+ * Flushes the window shadow tree so nothing is stored.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_shadow_tree_flush(void)
+{
+   _ecore_x_window_tree_shadow_free();
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c b/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c
new file mode 100644 (file)
index 0000000..52aaf96
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "ecore_xcb_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Xinerama_Group X Xinerama Extension Functions
+ *
+ * Functions related to the X Xinerama extension.
+ */
+
+
+#ifdef ECORE_XCB_XINERAMA
+static int _xinerama_available = 0;
+static xcb_xinerama_query_version_cookie_t _ecore_xcb_xinerama_init_cookie;
+#endif /* ECORE_XCB_XINERAMA */
+
+
+/* To avoid round trips, the initialization is separated in 2
+   functions: _ecore_xcb_xinerama_init and
+   _ecore_xcb_xinerama_init_finalize. The first one gets the cookies and
+   the second one gets the replies. */
+
+void
+_ecore_x_xinerama_init(const xcb_query_extension_reply_t *reply)
+{
+#ifdef ECORE_XCB_XINERAMA
+   if (reply && (reply->present))
+      _ecore_xcb_xinerama_init_cookie = xcb_xinerama_query_version_unchecked(_ecore_xcb_conn, 1, 2);
+#endif /* ECORE_XCB_XINERAMA */
+}
+
+void
+_ecore_x_xinerama_init_finalize(void)
+{
+#ifdef ECORE_XCB_XINERAMA
+   xcb_xinerama_query_version_reply_t *reply;
+
+   reply = xcb_xinerama_query_version_reply(_ecore_xcb_conn,
+                                          _ecore_xcb_xinerama_init_cookie, NULL);
+
+   if (reply)
+     {
+        if ((reply->major >= 1) &&
+            (reply->minor >= 1))
+          _xinerama_available = 1;
+        free(reply);
+     }
+#endif /* ECORE_XCB_XINERAMA */
+}
+
+
+/**
+ * Return whether the X server supports the Xinerama Extension.
+ * @return 1 if the X Xinerama Extension is available, 0 otherwise.
+ *
+ * Return 1 if the X server supports the Fixes Xinerama version 1.1,
+ * 0 otherwise.
+ * @ingroup Ecore_X_Xinerama_Group
+ */
+EAPI int
+ecore_x_xinerama_query(void)
+{
+#ifdef ECORE_XCB_XINERAMA
+   return _xinerama_available;
+#else
+   return 0;
+#endif /* ECORE_XCB_XINERAMA */
+}
+
+
+/**
+ * Sends the XineramaQueryScreens request.
+ * @ingroup Ecore_X_Xinerama_Group
+ */
+EAPI void
+ecore_x_xinerama_query_screens_prefetch(void)
+{
+#ifdef ECORE_XCB_XINERAMA
+   xcb_xinerama_query_screens_cookie_t cookie;
+
+   cookie = xcb_xinerama_query_screens_unchecked(_ecore_xcb_conn);
+   _ecore_xcb_cookie_cache(cookie.sequence);
+#endif /* ECORE_XCB_XINERAMA */
+}
+
+
+/**
+ * Gets the reply of the XineramaQueryScreens request sent by ecore_x_xinerama_query_screens_prefetch().
+ * @ingroup Ecore_X_Xinerama_Group
+ */
+EAPI void
+ecore_x_xinerama_query_screens_fetch(void)
+{
+#ifdef ECORE_XCB_XINERAMA
+   xcb_xinerama_query_screens_cookie_t cookie;
+   xcb_xinerama_query_screens_reply_t *reply;
+
+   cookie.sequence = _ecore_xcb_cookie_get();
+   reply = xcb_xinerama_query_screens_reply(_ecore_xcb_conn, cookie, NULL);
+   _ecore_xcb_reply_cache(reply);
+#endif /* ECORE_XCB_XINERAMA */
+}
+
+
+/**
+ * Return the number of screens.
+ * @return The screen count.
+ *
+ * Return the number of screens.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_xinerama_query_screens_prefetch(), which sends the XineramaQueryScreens request,
+ * then ecore_x_xinerama_query_screens_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Xinerama_Group
+ */
+EAPI int
+ecore_x_xinerama_screen_count_get(void)
+{
+   int                                 screen_count = 0;
+#ifdef ECORE_XCB_XINERAMA
+   xcb_xinerama_screen_info_iterator_t iter;
+   xcb_xinerama_query_screens_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply) return 0;
+
+   iter = xcb_xinerama_query_screens_screen_info_iterator(reply);
+   screen_count = iter.rem;
+#endif /* ECORE_XCB_XINERAMA */
+
+   return screen_count;
+}
+
+
+/**
+ * Get the geometry of the screen.
+ * @param screen The screen (Unused).
+ * @param x      The X coordinate of the screen.
+ * @param y      The Y coordinate of the screen
+ * @param width  The width of the screen
+ * @param height The height of the screen
+ * @return       1 on success, 0 otherwise.
+ *
+ * Get the geometry of the screen whose number is @p screen. The
+ * returned values are stored in @p x, @p y, @p width and @p height.
+ *
+ * To use this function, you must call before, and in order,
+ * ecore_x_xinerama_query_screens_prefetch(), which sends the XineramaQueryScreens request,
+ * then ecore_x_xinerama_query_screens_fetch(), which gets the reply.
+ * @ingroup Ecore_X_Xinerama_Group
+ */
+EAPI int
+ecore_x_xinerama_screen_geometry_get(int  screen,
+                                     int *x,
+                                     int *y,
+                                     int *width,
+                                     int *height)
+{
+#ifdef ECORE_XCB_XINERAMA
+   xcb_xinerama_screen_info_iterator_t iter;
+   xcb_xinerama_query_screens_reply_t *reply;
+
+   reply = _ecore_xcb_reply_get();
+   if (!reply)
+     {
+        if (x) *x = 0;
+        if (y) *y = 0;
+        if (width) *width = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels;
+        if (height) *height = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels;
+
+        return 0;
+     }
+
+   iter = xcb_xinerama_query_screens_screen_info_iterator(reply);
+   for (; iter.rem; screen--, xcb_xinerama_screen_info_next(&iter))
+     {
+        if (screen == 0)
+          {
+             if (x) *x = iter.data->x_org;
+             if (y) *y = iter.data->y_org;
+             if (width) *width = iter.data->width;
+             if (height) *height = iter.data->height;
+             return 1;
+          }
+     }
+#endif /* ECORE_XCB_XINERAMA */
+
+   if (x) *x = 0;
+   if (y) *y = 0;
+   if (width) *width = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels;
+   if (height) *height = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels;
+
+   return 0;
+}
diff --git a/src/lib/ecore_x/xlib/.cvsignore b/src/lib/ecore_x/xlib/.cvsignore
new file mode 100644 (file)
index 0000000..39b336e
--- /dev/null
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+libecore_x_xlib.la
diff --git a/src/lib/ecore_x/xlib/Makefile.am b/src/lib/ecore_x/xlib/Makefile.am
new file mode 100644 (file)
index 0000000..0757df4
--- /dev/null
@@ -0,0 +1,86 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+if BUILD_ECORE_X_XLIB
+
+AM_CPPFLAGS = \
+@Xcursor_cflags@ \
+@XKB_CFLAGS@ \
+@XDAMAGE_CFLAGS@ \
+@XCOMPOSITE_CFLAGS@ \
+@XDPMS_CFLAGS@ \
+@XFIXES_CFLAGS@ \
+@XI2_CFLAGS@ \
+@XINERAMA_CFLAGS@ \
+@XPRINT_CFLAGS@ \
+@XRANDR_CFLAGS@ \
+@XRENDER_CFLAGS@ \
+@XSS_CFLAGS@ \
+@XTEST_CFLAGS@ \
+@x_cflags@ \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_x \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_x \
+-I$(top_builddir)/src/lib/ecore_input \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+noinst_LTLIBRARIES = libecore_x_xlib.la
+
+libecore_x_xlib_la_SOURCES = \
+ecore_x.c \
+ecore_x_dnd.c \
+ecore_x_sync.c \
+ecore_x_randr.c \
+ecore_x_fixes.c \
+ecore_x_damage.c \
+ecore_x_composite.c \
+ecore_x_error.c \
+ecore_x_events.c \
+ecore_x_icccm.c \
+ecore_x_netwm.c \
+ecore_x_mwm.c \
+ecore_x_e.c \
+ecore_x_selection.c \
+ecore_x_window.c \
+ecore_x_window_prop.c \
+ecore_x_window_shape.c \
+ecore_x_pixmap.c \
+ecore_x_gc.c \
+ecore_x_xinerama.c \
+ecore_x_screensaver.c \
+ecore_x_dpms.c \
+ecore_x_drawable.c \
+ecore_x_cursor.c \
+ecore_x_test.c \
+ecore_x_atoms.c \
+ecore_x_region.c \
+ecore_x_image.c \
+ecore_x_xi2.c
+
+libecore_x_xlib_la_LIBADD = \
+@Xcursor_libs@ \
+@XKB_LIBS@ \
+@XDAMAGE_LIBS@ \
+@XCOMPOSITE_LIBS@ \
+@XDPMS_LIBS@ \
+@XFIXES_LIBS@ \
+@XI2_LIBS@ \
+@XINERAMA_LIBS@ \
+@XPRINT_LIBS@ \
+@XRANDR_LIBS@ \
+@XRENDER_LIBS@ \
+@XSS_LIBS@ \
+@XTEST_LIBS@ \
+@x_libs@ \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@EINA_LIBS@
+
+libecore_x_xlib_la_LDFLAGS = -version-info @version_info@
+
+endif
+
+EXTRA_DIST = ecore_x_private.h
diff --git a/src/lib/ecore_x/xlib/ecore_x.c b/src/lib/ecore_x/xlib/ecore_x.c
new file mode 100644 (file)
index 0000000..547b7ba
--- /dev/null
@@ -0,0 +1,1722 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+//#define LOGRT 1
+
+#ifdef LOGRT
+#include <dlfcn.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+#include "Ecore_Input.h"
+
+static int _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_x_key_mask_get(KeySym sym);
+static int _ecore_x_event_modifier(unsigned int state);
+
+static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL;
+
+static const int AnyXEvent = 0; /* 0 can be used as there are no event types
+                                * with index 0 and 1 as they are used for
+                                * errors
+                                */
+
+static int _ecore_x_event_shape_id = 0;
+static int _ecore_x_event_screensaver_id = 0;
+static int _ecore_x_event_sync_id = 0;
+int _ecore_xlib_log_dom = -1;
+
+#ifdef ECORE_XRANDR
+static int _ecore_x_event_randr_id = 0;
+#endif
+#ifdef ECORE_XFIXES
+static int _ecore_x_event_fixes_selection_id = 0;
+#endif
+#ifdef ECORE_XDAMAGE
+static int _ecore_x_event_damage_id = 0;
+#endif
+static int _ecore_x_event_handlers_num = 0;
+static void (**_ecore_x_event_handlers) (XEvent * event) = NULL;
+
+static int _ecore_x_init_count = 0;
+static int _ecore_x_grab_count = 0;
+
+Display *_ecore_x_disp = NULL;
+double   _ecore_x_double_click_time = 0.25;
+Time     _ecore_x_event_last_time = 0;
+Window   _ecore_x_event_last_win = 0;
+int      _ecore_x_event_last_root_x = 0;
+int      _ecore_x_event_last_root_y = 0;
+int      _ecore_x_xcursor = 0;
+XIC      _ecore_x_ic = NULL; /* Input context for composed characters */
+
+Ecore_X_Window _ecore_x_private_win = 0;
+
+Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
+
+EAPI int ECORE_X_EVENT_ANY = 0;
+EAPI int ECORE_X_EVENT_MOUSE_IN = 0;
+EAPI int ECORE_X_EVENT_MOUSE_OUT = 0;
+EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0;
+EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0;
+EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0;
+EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0;
+EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0;
+EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STACK = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0;
+EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0;
+EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0;
+EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0;
+EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0;
+EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0;
+EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0;
+EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0;
+EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0;
+EAPI int ECORE_X_EVENT_SYNC_ALARM = 0;
+EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0;
+EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0;
+EAPI int ECORE_X_EVENT_RANDR_CRTC_CHANGE = 0;
+EAPI int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = 0;
+EAPI int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = 0;
+EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0;
+/*
+EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0;
+EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0;
+*/
+
+EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0;
+EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0;
+EAPI int ECORE_X_EVENT_PING = 0;
+EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0;
+
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0;
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0;
+EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0;
+
+EAPI int ECORE_X_EVENT_GENERIC = 0;
+
+int ECORE_X_MODIFIER_SHIFT = 0;
+int ECORE_X_MODIFIER_CTRL = 0;
+int ECORE_X_MODIFIER_ALT = 0;
+int ECORE_X_MODIFIER_WIN = 0;
+
+EAPI int ECORE_X_LOCK_SCROLL = 0;
+EAPI int ECORE_X_LOCK_NUM = 0;
+EAPI int ECORE_X_LOCK_CAPS = 0;
+
+#ifdef LOGRT
+static double t0 = 0.0;
+static Status (*_logrt_real_reply) (Display *disp, void *rep, int extra, Bool discard) = NULL;
+static void
+_logrt_init(void)
+{
+   void *lib;
+   
+   lib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
+   if (!lib) lib = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY);
+   if (!lib) lib = dlopen("libX11.so.6.3", RTLD_GLOBAL | RTLD_LAZY);
+   if (!lib) lib = dlopen("libX11.so.6.3.0", RTLD_GLOBAL | RTLD_LAZY);
+   _logrt_real_reply = dlsym(lib, "_XReply");
+   t0 = ecore_time_get();
+}
+Status
+_XReply(Display *disp, void *rep, int extra, Bool discard)
+{
+   void *bt[128];
+   int i, n;
+   char **sym;
+   
+   n = backtrace(bt, 128);
+   if (n > 0)
+     {
+        sym = backtrace_symbols(bt, n);
+        printf("ROUNDTRIP: %4.4f :", ecore_time_get() - t0);
+        if (sym)
+          {
+             for (i = n - 1; i > 0; i--)
+               {
+                  char *fname = strchr(sym[i], '(');
+                  if (fname)
+                    {
+                       char *tsym = alloca(strlen(fname) + 1);
+                       char *end;
+                       strcpy(tsym, fname + 1);
+                       end = strchr(tsym, '+');
+                       if (end)
+                         {
+                            *end = 0;
+                            printf("%s", tsym);
+                         }
+                       else
+                         printf("???");
+                    }
+                  else
+                    printf("???");
+                  if (i > 1) printf(" > ");
+               }
+             printf("\n");
+          }
+     }
+   // fixme: logme
+   return _logrt_real_reply(disp, rep, extra, discard);
+}
+#endif
+
+/**
+ * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
+ *
+ * Functions that start and shut down the Ecore X Library.
+ */
+
+/**
+ * Initialize the X display connection to the given display.
+ *
+ * @param   name Display target name.  If @c NULL, the default display is
+ *               assumed.
+ * @return  The number of times the library has been initialized without
+ *          being shut down.  0 is returned if an error occurs.
+ * @ingroup Ecore_X_Init_Group
+ */
+EAPI int
+ecore_x_init(const char *name)
+{
+   int shape_base = 0;
+   int shape_err_base = 0;
+#ifdef ECORE_XSS
+   int screensaver_base = 0;
+   int screensaver_err_base = 0;
+#endif
+   int sync_base = 0;
+   int sync_err_base = 0;
+#ifdef ECORE_XRANDR
+   int randr_base = 0;
+   int randr_err_base = 0;
+#endif
+#ifdef ECORE_XFIXES
+   int fixes_base = 0;
+   int fixes_err_base = 0;
+#endif
+#ifdef ECORE_XDAMAGE
+   int damage_base = 0;
+   int damage_err_base = 0;
+#endif
+   
+   if (++_ecore_x_init_count != 1) 
+     return _ecore_x_init_count;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef LOGRT
+   _logrt_init();
+#endif   
+   
+   _ecore_xlib_log_dom = eina_log_domain_register("EcoreX11", ECORE_XLIB_DEFAULT_LOG_COLOR);
+   if(_ecore_xlib_log_dom < 0)
+     {
+       EINA_LOG_ERR("Impossible to create a log domain for the Ecore Xlib module.");
+       return --_ecore_x_init_count;
+     }
+   if (!ecore_event_init())
+     {
+       eina_log_domain_unregister(_ecore_xlib_log_dom);
+       _ecore_xlib_log_dom = -1;
+       return --_ecore_x_init_count;
+     }
+   _ecore_x_disp = XOpenDisplay((char *)name);
+   if (!_ecore_x_disp)
+     goto shutdown_ecore_event;
+
+   _ecore_x_error_handler_init();
+   _ecore_x_event_handlers_num = LASTEvent;
+
+#define ECORE_X_EVENT_HANDLERS_GROW(ext_base, ext_num_events)          \
+   do {                                                                        \
+     if (_ecore_x_event_handlers_num < (ext_base + ext_num_events))    \
+       _ecore_x_event_handlers_num = (ext_base + ext_num_events);      \
+   } while (0)
+
+   if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base))
+     _ecore_x_event_shape_id = shape_base;
+   ECORE_X_EVENT_HANDLERS_GROW(shape_base, ShapeNumberEvents);
+
+#ifdef ECORE_XSS
+   if (XScreenSaverQueryExtension(_ecore_x_disp, &screensaver_base, &screensaver_err_base))
+     _ecore_x_event_screensaver_id = screensaver_base;
+   ECORE_X_EVENT_HANDLERS_GROW(screensaver_base, ScreenSaverNumberEvents);
+#endif
+
+   if (XSyncQueryExtension(_ecore_x_disp, &sync_base, &sync_err_base))
+     {
+       int major, minor;
+
+       _ecore_x_event_sync_id = sync_base;
+       if (!XSyncInitialize(_ecore_x_disp, &major, &minor))
+         _ecore_x_event_sync_id = 0;
+     }
+   ECORE_X_EVENT_HANDLERS_GROW(sync_base, XSyncNumberEvents);
+
+#ifdef ECORE_XRANDR
+   if (XRRQueryExtension(_ecore_x_disp, &randr_base, &randr_err_base))
+     _ecore_x_event_randr_id = randr_base;
+   ECORE_X_EVENT_HANDLERS_GROW(randr_base, RRNumberEvents);
+#endif
+
+#ifdef ECORE_XFIXES
+   if (XFixesQueryExtension(_ecore_x_disp, &fixes_base, &fixes_err_base))
+     _ecore_x_event_fixes_selection_id = fixes_base;
+   ECORE_X_EVENT_HANDLERS_GROW(fixes_base, XFixesNumberEvents);
+#endif
+
+#ifdef ECORE_XDAMAGE
+   if (XDamageQueryExtension(_ecore_x_disp, &damage_base, &damage_err_base))
+     _ecore_x_event_damage_id = damage_base;
+   ECORE_X_EVENT_HANDLERS_GROW(damage_base, XDamageNumberEvents);
+#endif
+
+   _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(void *));
+   if (!_ecore_x_event_handlers)
+     goto close_display;
+
+#ifdef ECORE_XCURSOR   
+   _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp);
+#endif
+   _ecore_x_event_handlers[AnyXEvent]        = _ecore_x_event_handle_any_event;
+   _ecore_x_event_handlers[KeyPress]         = _ecore_x_event_handle_key_press;
+   _ecore_x_event_handlers[KeyRelease]       = _ecore_x_event_handle_key_release;
+   _ecore_x_event_handlers[ButtonPress]      = _ecore_x_event_handle_button_press;
+   _ecore_x_event_handlers[ButtonRelease]    = _ecore_x_event_handle_button_release;
+   _ecore_x_event_handlers[MotionNotify]     = _ecore_x_event_handle_motion_notify;
+   _ecore_x_event_handlers[EnterNotify]      = _ecore_x_event_handle_enter_notify;
+   _ecore_x_event_handlers[LeaveNotify]      = _ecore_x_event_handle_leave_notify;
+   _ecore_x_event_handlers[FocusIn]          = _ecore_x_event_handle_focus_in;
+   _ecore_x_event_handlers[FocusOut]         = _ecore_x_event_handle_focus_out;
+   _ecore_x_event_handlers[KeymapNotify]     = _ecore_x_event_handle_keymap_notify;
+   _ecore_x_event_handlers[Expose]           = _ecore_x_event_handle_expose;
+   _ecore_x_event_handlers[GraphicsExpose]   = _ecore_x_event_handle_graphics_expose;
+   _ecore_x_event_handlers[VisibilityNotify] = _ecore_x_event_handle_visibility_notify;
+   _ecore_x_event_handlers[CreateNotify]     = _ecore_x_event_handle_create_notify;
+   _ecore_x_event_handlers[DestroyNotify]    = _ecore_x_event_handle_destroy_notify;
+   _ecore_x_event_handlers[UnmapNotify]      = _ecore_x_event_handle_unmap_notify;
+   _ecore_x_event_handlers[MapNotify]        = _ecore_x_event_handle_map_notify;
+   _ecore_x_event_handlers[MapRequest]       = _ecore_x_event_handle_map_request;
+   _ecore_x_event_handlers[ReparentNotify]   = _ecore_x_event_handle_reparent_notify;
+   _ecore_x_event_handlers[ConfigureNotify]  = _ecore_x_event_handle_configure_notify;
+   _ecore_x_event_handlers[ConfigureRequest] = _ecore_x_event_handle_configure_request;
+   _ecore_x_event_handlers[GravityNotify]    = _ecore_x_event_handle_gravity_notify;
+   _ecore_x_event_handlers[ResizeRequest]    = _ecore_x_event_handle_resize_request;
+   _ecore_x_event_handlers[CirculateNotify]  = _ecore_x_event_handle_circulate_notify;
+   _ecore_x_event_handlers[CirculateRequest] = _ecore_x_event_handle_circulate_request;
+   _ecore_x_event_handlers[PropertyNotify]   = _ecore_x_event_handle_property_notify;
+   _ecore_x_event_handlers[SelectionClear]   = _ecore_x_event_handle_selection_clear;
+   _ecore_x_event_handlers[SelectionRequest] = _ecore_x_event_handle_selection_request;
+   _ecore_x_event_handlers[SelectionNotify]  = _ecore_x_event_handle_selection_notify;
+   _ecore_x_event_handlers[ColormapNotify]   = _ecore_x_event_handle_colormap_notify;
+   _ecore_x_event_handlers[ClientMessage]    = _ecore_x_event_handle_client_message;
+   _ecore_x_event_handlers[MappingNotify]    = _ecore_x_event_handle_mapping_notify;
+#ifdef GenericEvent
+  _ecore_x_event_handlers[GenericEvent]    = _ecore_x_event_handle_generic_event;      
+#endif
+   
+   if (_ecore_x_event_shape_id)
+     _ecore_x_event_handlers[_ecore_x_event_shape_id] = _ecore_x_event_handle_shape_change;
+   if (_ecore_x_event_screensaver_id)
+     _ecore_x_event_handlers[_ecore_x_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify;
+   if (_ecore_x_event_sync_id)
+     {
+       _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncCounterNotify] =
+          _ecore_x_event_handle_sync_counter;
+       _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncAlarmNotify] =
+          _ecore_x_event_handle_sync_alarm;
+     }
+#ifdef ECORE_XRANDR
+   if (_ecore_x_event_randr_id)
+     {
+       _ecore_x_event_handlers[_ecore_x_event_randr_id + RRScreenChangeNotify] = _ecore_x_event_handle_randr_change;
+       _ecore_x_event_handlers[_ecore_x_event_randr_id + RRNotify] = _ecore_x_event_handle_randr_notify;
+     }
+#endif
+#ifdef ECORE_XFIXES
+   if (_ecore_x_event_fixes_selection_id)
+     _ecore_x_event_handlers[_ecore_x_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify;
+#endif
+#ifdef ECORE_XDAMAGE
+   if (_ecore_x_event_damage_id)
+     _ecore_x_event_handlers[_ecore_x_event_damage_id] = _ecore_x_event_handle_damage_notify;
+#endif
+#ifdef ECORE_XKB
+   // set x autorepeat detection to on. that means instead of
+   //   press-release-press-release-press-release
+   // you get
+   //   press-press-press-press-press-release
+   do
+     {
+        Bool works = 0;
+        XkbSetDetectableAutoRepeat(_ecore_x_disp, 1, &works);
+     }
+   while (0);
+#endif
+   
+   if (!ECORE_X_EVENT_ANY)
+     {
+       ECORE_X_EVENT_ANY                      = ecore_event_type_new();
+       ECORE_X_EVENT_MOUSE_IN                 = ecore_event_type_new();
+       ECORE_X_EVENT_MOUSE_OUT                = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_FOCUS_IN          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_FOCUS_OUT         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_KEYMAP            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_DAMAGE            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CREATE            = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_DESTROY           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_HIDE              = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHOW              = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHOW_REQUEST      = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_REPARENT          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CONFIGURE         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_GRAVITY           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_RESIZE_REQUEST    = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STACK             = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STACK_REQUEST     = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROPERTY          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_COLORMAP          = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_MAPPING           = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_CLEAR          = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_REQUEST        = ecore_event_type_new();
+       ECORE_X_EVENT_SELECTION_NOTIFY         = ecore_event_type_new();
+       ECORE_X_EVENT_CLIENT_MESSAGE           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_SHAPE             = ecore_event_type_new();
+       ECORE_X_EVENT_SCREENSAVER_NOTIFY       = ecore_event_type_new();
+       ECORE_X_EVENT_SYNC_COUNTER             = ecore_event_type_new();
+       ECORE_X_EVENT_SYNC_ALARM               = ecore_event_type_new();
+       ECORE_X_EVENT_SCREEN_CHANGE            = ecore_event_type_new();
+       ECORE_X_EVENT_RANDR_CRTC_CHANGE        = ecore_event_type_new();
+       ECORE_X_EVENT_RANDR_OUTPUT_CHANGE      = ecore_event_type_new();
+       ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = ecore_event_type_new();
+       ECORE_X_EVENT_DAMAGE_NOTIFY            = ecore_event_type_new();
+       
+       ECORE_X_EVENT_WINDOW_DELETE_REQUEST                = ecore_event_type_new();
+       /*
+       ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE             = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE     = ecore_event_type_new();
+        ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE        = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE         = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE    = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE               = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE           = ecore_event_type_new();
+       */
+
+       ECORE_X_EVENT_DESKTOP_CHANGE           = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new();
+       ECORE_X_EVENT_WINDOW_STATE_REQUEST     = ecore_event_type_new();
+       ECORE_X_EVENT_FRAME_EXTENTS_REQUEST    = ecore_event_type_new();
+       ECORE_X_EVENT_PING                     = ecore_event_type_new();
+
+       ECORE_X_EVENT_STARTUP_SEQUENCE_NEW     = ecore_event_type_new();
+       ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE  = ecore_event_type_new();
+       ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE  = ecore_event_type_new();
+
+       ECORE_X_EVENT_GENERIC                  = ecore_event_type_new();
+     }
+   
+   /* everything has these... unless its like a pda... :) */
+   ECORE_X_MODIFIER_SHIFT = _ecore_x_key_mask_get(XK_Shift_L);
+   ECORE_X_MODIFIER_CTRL  = _ecore_x_key_mask_get(XK_Control_L);
+   
+   /* apple's xdarwin has no alt!!!! */
+   ECORE_X_MODIFIER_ALT   = _ecore_x_key_mask_get(XK_Alt_L);
+   if (!ECORE_X_MODIFIER_ALT) 
+     ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Meta_L);
+   if (!ECORE_X_MODIFIER_ALT) 
+     ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Super_L);   
+   
+   /* the windows key... a valid modifier :) */
+   ECORE_X_MODIFIER_WIN   = _ecore_x_key_mask_get(XK_Super_L);
+   if (!ECORE_X_MODIFIER_WIN) 
+     ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Mode_switch);
+   if (!ECORE_X_MODIFIER_WIN) 
+     ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Meta_L);
+   
+   if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
+     ECORE_X_MODIFIER_WIN = 0;
+   if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
+     ECORE_X_MODIFIER_ALT = 0;
+   
+   ECORE_X_LOCK_SCROLL    = _ecore_x_key_mask_get(XK_Scroll_Lock);
+   ECORE_X_LOCK_NUM       = _ecore_x_key_mask_get(XK_Num_Lock);
+   ECORE_X_LOCK_CAPS      = _ecore_x_key_mask_get(XK_Caps_Lock);
+   
+   _ecore_x_fd_handler_handle = 
+     ecore_main_fd_handler_add(ConnectionNumber(_ecore_x_disp),
+                              ECORE_FD_READ,
+                              _ecore_x_fd_handler, _ecore_x_disp,
+                              _ecore_x_fd_handler_buf, _ecore_x_disp);
+   if (!_ecore_x_fd_handler_handle)
+     goto free_event_handlers;
+
+   _ecore_x_atoms_init();
+
+   /* Set up the ICCCM hints */
+   ecore_x_icccm_init();
+
+   /* Set up the _NET_... hints */
+   ecore_x_netwm_init();
+
+   /* old e hints init */
+   ecore_x_e_init();
+   
+   /* This is just to be anal about naming conventions */
+
+   _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW;
+   _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS;
+   _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING;
+   _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
+
+   _ecore_x_selection_data_init();
+   _ecore_x_dnd_init();
+   _ecore_x_fixes_init();
+   _ecore_x_damage_init();
+   _ecore_x_composite_init();
+   _ecore_x_dpms_init();
+   _ecore_x_randr_init();
+   _ecore_x_input_init();
+   
+   _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456);
+
+#ifdef ENABLE_XIM
+   /* Setup XIM */
+   if (!_ecore_x_ic && XSupportsLocale())
+     {
+       XIM im;
+       XIC ic;
+       XIMStyles *supported_styles;
+       XIMStyle chosen_style = 0;
+       Ecore_X_Window client_window = ecore_x_window_root_get(_ecore_x_private_win);
+       char *ret;
+       int i;
+
+       XSetLocaleModifiers("@im=none");
+       if ((im = XOpenIM(_ecore_x_disp, NULL, NULL, NULL)) == NULL)
+         goto _im_create_end;
+       ret = XGetIMValues(im, XNQueryInputStyle, &supported_styles, NULL);
+       if (ret || !supported_styles)
+         goto _im_create_error;
+       for (i = 0; i < supported_styles->count_styles; i++)
+         if (supported_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing))
+           chosen_style = supported_styles->supported_styles[i];
+       XFree(supported_styles);
+       if (!chosen_style)
+         goto _im_create_error;
+       ic = XCreateIC(im, XNInputStyle, chosen_style, XNClientWindow, client_window, NULL);
+       if (ic)
+         {
+            _ecore_x_ic = ic;
+            goto _im_create_end;
+         }
+_im_create_error:
+       XCloseIM(im);
+     }
+_im_create_end:
+#endif
+   return _ecore_x_init_count;
+
+ free_event_handlers:
+   free(_ecore_x_event_handlers);
+   _ecore_x_event_handlers = NULL;
+ close_display:
+   XCloseDisplay(_ecore_x_disp);
+   _ecore_x_fd_handler_handle = NULL;
+   _ecore_x_disp = NULL;
+ shutdown_ecore_event:
+   ecore_event_shutdown();
+
+   return --_ecore_x_init_count;
+}
+
+static int
+_ecore_x_shutdown(int close_display)
+{
+   if (--_ecore_x_init_count != 0)
+     return _ecore_x_init_count;
+
+   if (!_ecore_x_disp) return _ecore_x_init_count;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+#ifdef ENABLE_XIM
+   if (_ecore_x_ic)
+     {
+       XIM xim;
+       xim = XIMOfIC(_ecore_x_ic);
+       XDestroyIC(_ecore_x_ic);
+       XCloseIM(xim);
+       _ecore_x_ic = NULL;
+     }
+#endif
+   if (close_display)
+      XCloseDisplay(_ecore_x_disp);
+   else
+      close(ConnectionNumber(_ecore_x_disp));
+   free(_ecore_x_event_handlers);
+   ecore_main_fd_handler_del(_ecore_x_fd_handler_handle);
+   _ecore_x_fd_handler_handle = NULL;
+   _ecore_x_disp = NULL;
+   _ecore_x_event_handlers = NULL;
+   _ecore_x_input_shutdown();
+   _ecore_x_selection_shutdown();
+   _ecore_x_dnd_shutdown();
+   ecore_x_netwm_shutdown();
+   ecore_event_shutdown();
+   eina_log_domain_unregister(_ecore_xlib_log_dom);
+   _ecore_xlib_log_dom = -1;
+   return _ecore_x_init_count;
+}
+
+/**
+ * Shuts down the Ecore X library.
+ *
+ * In shutting down the library, the X display connection is terminated
+ * and any event handlers for it are removed.
+ *
+ * @return  The number of times the library has been initialized without
+ *          being shut down.
+ * @ingroup Ecore_X_Init_Group
+ */
+EAPI int
+ecore_x_shutdown(void)
+{
+   return _ecore_x_shutdown(1);
+}
+
+/**
+ * Shuts down the Ecore X library.
+ *
+ * As ecore_x_shutdown, except do not close Display, only connection.
+ *
+ * @ingroup Ecore_X_Init_Group
+ */
+EAPI int
+ecore_x_disconnect(void)
+{
+   return _ecore_x_shutdown(0);
+}
+
+/**
+ * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
+ *
+ * Functions that set and retrieve X display attributes.
+ */
+
+/**
+ * Retrieves the Ecore_X_Display handle used for the current X connection.
+ * @return  The current X display.
+ * @ingroup Ecore_X_Display_Attr_Group
+ */
+EAPI Ecore_X_Display *
+ecore_x_display_get(void)
+{
+   return (Ecore_X_Display *)_ecore_x_disp;
+}
+
+/**
+ * Retrieves the X display file descriptor.
+ * @return  The current X display file descriptor.
+ * @ingroup Ecore_X_Display_Attr_Group
+ */
+EAPI int
+ecore_x_fd_get(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ConnectionNumber(_ecore_x_disp);
+}
+
+/**
+ * Retrieves the Ecore_X_Screen handle used for the current X connection.
+ * @return  The current default screen.
+ * @ingroup Ecore_Xcb_Display_Attr_Group
+ */
+EAPI Ecore_X_Screen*
+ecore_x_default_screen_get(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return (Ecore_X_Screen*) DefaultScreenOfDisplay(_ecore_x_disp);
+}
+
+/**
+ * Sets the timeout for a double and triple clicks to be flagged.
+ * 
+ * This sets the time between clicks before the double_click flag is
+ * set in a button down event. If 3 clicks occur within double this
+ * time, the triple_click flag is also set.
+ *
+ * @param   t The time in seconds
+ * @ingroup Ecore_X_Display_Attr_Group
+ */
+EAPI void
+ecore_x_double_click_time_set(double t)
+{
+   if (t < 0.0) t = 0.0;
+   _ecore_x_double_click_time = t;
+}
+
+/**
+ * Retrieves the double and triple click flag timeout.
+ *
+ * See @ref ecore_x_double_click_time_set for more information.
+ *
+ * @return  The timeout for double clicks in seconds.
+ * @ingroup Ecore_X_Display_Attr_Group
+ */
+EAPI double
+ecore_x_double_click_time_get(void)
+{
+   return _ecore_x_double_click_time;
+}
+
+/**
+ * @defgroup Ecore_X_Flush_Group X Synchronization Functions
+ *
+ * Functions that ensure that all commands that have been issued by the
+ * Ecore X library have been sent to the server.
+ */
+
+/**
+ * Sends all X commands in the X Display buffer.
+ * @ingroup Ecore_X_Flush_Group
+ */
+EAPI void
+ecore_x_flush(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFlush(_ecore_x_disp);
+}
+
+/**
+ * Flushes the command buffer and waits until all requests have been
+ * processed by the server.
+ * @ingroup Ecore_X_Flush_Group
+ */
+EAPI void
+ecore_x_sync(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSync(_ecore_x_disp, False);
+}
+
+/**
+ * Kill all clients with subwindows under a given window.
+ *
+ * You can kill all clients connected to the X server by using
+ * @ref ecore_x_window_root_list to get a list of root windows, and
+ * then passing each root window to this function.
+ *
+ * @param root The window whose children will be killed.
+ */
+EAPI void
+ecore_x_killall(Ecore_X_Window root)
+{
+   unsigned int j;
+   Window root_r;
+   Window parent_r;
+   Window *children_r = NULL;
+   unsigned int num_children = 0;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGrabServer(_ecore_x_disp);
+   /* Tranverse window tree starting from root, and drag each
+    * before the firing squad */
+   while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r,
+                    &children_r, &num_children) && (num_children > 0))
+     {
+       for (j = 0; j < num_children; ++j)
+         {
+            XKillClient(_ecore_x_disp, children_r[j]);
+         }
+       
+       XFree(children_r);
+     }
+   XUngrabServer(_ecore_x_disp);
+   XSync(_ecore_x_disp, False);
+}
+
+/**
+ * Kill a specific client
+ *
+ * You can kill a specific client owning window @p win
+ *
+ * @param win Window of the client to be killed
+ */
+EAPI void
+ecore_x_kill(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XKillClient(_ecore_x_disp, win);
+}
+
+/**
+ * Return the last event time
+ */
+EAPI Ecore_X_Time
+ecore_x_current_time_get(void)
+{
+   return _ecore_x_event_last_time;
+}
+
+/**
+ * Return the screen DPI
+ *
+ * This is a simplistic call to get DPI. It does not account for differing
+ * DPI in the x amd y axes nor does it accoutn for multihead or xinerama and
+ * xrander where different parts of the screen may have differen DPI etc.
+ *
+ * @return the general screen DPI (dots/pixels per inch).
+ */
+EAPI int
+ecore_x_dpi_get(void)
+{
+   Screen *s;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   s = DefaultScreenOfDisplay(_ecore_x_disp);
+   if (s->mwidth <= 0) return 75;
+   return (((s->width * 254) / s->mwidth) + 5) / 10;
+}
+
+static int
+_ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Display *d;
+   
+   d = data;
+   while (XPending(d))
+     {
+       XEvent ev;
+       
+       XNextEvent(d, &ev);
+
+#ifdef ENABLE_XIM
+       /* Filter event for XIM */
+       if (XFilterEvent(&ev, ev.xkey.window)) continue;
+#endif
+
+       if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num))
+         {
+            if (_ecore_x_event_handlers[AnyXEvent])
+              _ecore_x_event_handlers[AnyXEvent] (&ev);
+
+            if (_ecore_x_event_handlers[ev.type])
+              _ecore_x_event_handlers[ev.type] (&ev);
+         }
+     }
+   return 1;
+}
+
+static int
+_ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Display *d;
+
+   d = data;
+   if (XPending(d)) return 1;
+   return 0;
+}
+
+static int
+_ecore_x_key_mask_get(KeySym sym)
+{
+   XModifierKeymap    *mod;
+   KeySym              sym2;
+   int                 i, j;
+   const int           masks[8] = 
+     {
+       ShiftMask, LockMask, ControlMask, 
+         Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+     };
+   
+   mod = XGetModifierMapping(_ecore_x_disp);
+   if ((mod) && (mod->max_keypermod > 0))
+     {
+       for (i = 0; i < (8 * mod->max_keypermod); i++)
+         {
+            for (j = 0; j < 8; j++)
+              {
+                 sym2 = XKeycodeToKeysym(_ecore_x_disp, mod->modifiermap[i], j);
+                 if (sym2 != 0) break;
+              }
+            if (sym2 == sym)
+              {
+                 int mask;
+                 
+                 mask = masks[i / mod->max_keypermod];
+                 if (mod->modifiermap) XFree(mod->modifiermap);
+                 XFree(mod);
+                 return mask;
+              }
+         }
+     }
+   if (mod)
+     {
+       if (mod->modifiermap) XFree(mod->modifiermap);
+       XFree(mod);
+     }
+  return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/* FIXME: these funcs need categorising */
+/*****************************************************************************/
+
+/**
+ * Get a list of all the root windows on the server.
+ *
+ * @note   The returned array will need to be freed after use.
+ * @param  num_ret Pointer to integer to put number of windows returned in.
+ * @return An array of all the root windows.  @c NULL is returned if memory
+ *         could not be allocated for the list, or if @p num_ret is @c NULL.
+ */
+EAPI Ecore_X_Window *
+ecore_x_window_root_list(int *num_ret)
+{
+   int num, i;
+   Ecore_X_Window *roots;
+#ifdef ECORE_XPRINT
+   int xp_base, xp_err_base;
+#endif
+   
+   if (!num_ret) return NULL;
+   *num_ret = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef ECORE_XPRINT
+   num = ScreenCount(_ecore_x_disp);
+   if (XpQueryExtension(_ecore_x_disp, &xp_base, &xp_err_base))
+     {
+       Screen **ps = NULL;
+       int psnum = 0;
+       
+       ps = XpQueryScreens(_ecore_x_disp, &psnum);
+       if (ps)
+         {
+            int overlap, j;
+            
+            overlap = 0;
+            for (i = 0; i < num; i++)
+              {
+                 for (j = 0; j < psnum; j++)
+                   {
+                      if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
+                        overlap++;
+                   }
+              }
+            roots = malloc((num - overlap) * sizeof(Window));
+            if (roots)
+              {
+                 int k;
+                 
+                 k = 0;
+                 for (i = 0; i < num; i++)
+                   {
+                      int is_print;
+                      
+                      is_print = 0;
+                      for (j = 0; j < psnum; j++)
+                        {
+                           if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
+                             {
+                                is_print = 1;
+                                break;
+                             }
+                        }
+                      if (!is_print)
+                        {
+                           roots[k] = RootWindow(_ecore_x_disp, i);
+                           k++;
+                        }
+                   }
+                 *num_ret = k;
+              }
+            XFree(ps);
+         }
+       else
+         {
+            roots = malloc(num * sizeof(Window));
+            if (!roots) return NULL;
+            *num_ret = num;
+            for (i = 0; i < num; i++)
+              roots[i] = RootWindow(_ecore_x_disp, i);
+         }
+     }
+   else
+     {
+       roots = malloc(num * sizeof(Window));
+       if (!roots) return NULL;
+       *num_ret = num;
+       for (i = 0; i < num; i++)
+         roots[i] = RootWindow(_ecore_x_disp, i);
+     }
+#else   
+   num = ScreenCount(_ecore_x_disp);
+   roots = malloc(num * sizeof(Window));
+   if (!roots) return NULL;
+   *num_ret = num;
+   for (i = 0; i < num; i++)
+     roots[i] = RootWindow(_ecore_x_disp, i);
+#endif   
+   return roots;
+}
+
+EAPI Ecore_X_Window
+ecore_x_window_root_first_get(void)
+{
+   return RootWindow(_ecore_x_disp, 0);
+/*   
+   int num;
+   Ecore_X_Window root, *roots = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   roots = ecore_x_window_root_list(&num);
+   if (!(roots)) return 0;
+   
+   if (num > 0)
+     root = roots[0];
+   else
+     root = 0;
+   
+   free(roots);
+   return root;
+ */
+}
+
+
+static void _ecore_x_window_manage_error(void *data);
+
+static int _ecore_x_window_manage_failed = 0;
+static void
+_ecore_x_window_manage_error(void *data __UNUSED__)
+{
+   if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) &&
+       (ecore_x_error_code_get() == BadAccess))
+     _ecore_x_window_manage_failed = 1;
+}
+
+EAPI int
+ecore_x_window_manage(Ecore_X_Window win)
+{
+   XWindowAttributes   att;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True) return 0;
+   ecore_x_sync();
+   _ecore_x_window_manage_failed = 0;
+   ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL);
+   XSelectInput(_ecore_x_disp, win, 
+               EnterWindowMask | 
+               LeaveWindowMask | 
+               PropertyChangeMask | 
+               ResizeRedirectMask |
+               SubstructureRedirectMask | 
+               SubstructureNotifyMask |
+               StructureNotifyMask |
+               KeyPressMask | 
+               KeyReleaseMask |
+               att.your_event_mask);
+   ecore_x_sync();
+   ecore_x_error_handler_set(NULL, NULL);
+   if (_ecore_x_window_manage_failed)
+     {
+       _ecore_x_window_manage_failed = 0;
+       return 0;
+     }
+   return 1;
+}
+
+EAPI void
+ecore_x_window_container_manage(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSelectInput(_ecore_x_disp, win, 
+               SubstructureRedirectMask | 
+               SubstructureNotifyMask);
+}
+
+EAPI void
+ecore_x_window_client_manage(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSelectInput(_ecore_x_disp, win, 
+               PropertyChangeMask | 
+//             ResizeRedirectMask |
+               FocusChangeMask |
+               ColormapChangeMask |
+               VisibilityChangeMask |
+               StructureNotifyMask |
+                SubstructureNotifyMask
+               );
+   XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
+}
+
+EAPI void
+ecore_x_window_sniff(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSelectInput(_ecore_x_disp, win,
+               PropertyChangeMask |
+               SubstructureNotifyMask);
+}
+
+EAPI void
+ecore_x_window_client_sniff(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSelectInput(_ecore_x_disp, win,
+               PropertyChangeMask |
+               FocusChangeMask |
+               ColormapChangeMask |
+               VisibilityChangeMask |
+               StructureNotifyMask |
+                SubstructureNotifyMask);
+   XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
+}
+
+
+
+
+
+
+EAPI int
+ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret)
+{
+   XWindowAttributes att;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
+   memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
+   att_ret->root = att.root;
+   att_ret->x = att.x;
+   att_ret->y = att.y;
+   att_ret->w = att.width;
+   att_ret->h = att.height;
+   att_ret->border = att.border_width;
+   att_ret->depth = att.depth;
+   if (att.map_state != IsUnmapped) att_ret->visible = 1;
+   if (att.map_state == IsViewable) att_ret->viewable = 1;
+   if (att.override_redirect) att_ret->override = 1;
+   if (att.class == InputOnly) att_ret->input_only = 1;
+   if (att.save_under) att_ret->save_under = 1;
+   att_ret->event_mask.mine = att.your_event_mask;
+   att_ret->event_mask.all = att.all_event_masks;
+   att_ret->event_mask.no_propagate = att.do_not_propagate_mask;
+   att_ret->window_gravity = att.win_gravity;
+   att_ret->pixel_gravity = att.bit_gravity;
+   att_ret->colormap = att.colormap;
+   att_ret->visual = att.visual;
+   return 1;
+}
+
+EAPI void
+ecore_x_window_save_set_add(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XAddToSaveSet(_ecore_x_disp, win);
+}
+
+EAPI void
+ecore_x_window_save_set_del(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XRemoveFromSaveSet(_ecore_x_disp, win);
+}
+
+EAPI Ecore_X_Window *
+ecore_x_window_children_get(Ecore_X_Window win, int *num)
+{
+   Ecore_X_Window     *windows = NULL;
+   Window              root_ret = 0, parent_ret = 0, *children_ret = NULL;
+   unsigned int        children_ret_num = 0;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret,
+                  &children_ret_num))
+     {
+       return NULL;
+     }
+   if (children_ret)
+     {
+       windows = malloc(children_ret_num * sizeof(Ecore_X_Window));
+       if (windows)
+         {
+            unsigned int i;
+            
+            for (i = 0; i < children_ret_num; i++)
+              windows[i] = children_ret[i];
+            *num = children_ret_num;
+         }
+       XFree(children_ret);
+     }
+   return windows;
+}
+
+EAPI int
+ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XChangePointerControl(_ecore_x_disp, 1, 1, 
+                               accel_num, accel_denom, threshold);
+}
+
+EAPI int
+ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XGetPointerControl(_ecore_x_disp, 
+                               accel_num, accel_denom, threshold);
+}
+
+EAPI int
+ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XSetPointerMapping(_ecore_x_disp, map, nmap);
+}
+
+EAPI int
+ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XGetPointerMapping(_ecore_x_disp, map, nmap);
+}
+
+EAPI int
+ecore_x_pointer_grab(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XGrabPointer(_ecore_x_disp, win, False,
+                   ButtonPressMask | ButtonReleaseMask | 
+                   EnterWindowMask | LeaveWindowMask | PointerMotionMask,
+                   GrabModeAsync, GrabModeAsync,
+                   None, None, CurrentTime) == GrabSuccess) return 1;
+   return 0;
+}
+
+EAPI int
+ecore_x_pointer_confine_grab(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XGrabPointer(_ecore_x_disp, win, False,
+                   ButtonPressMask | ButtonReleaseMask | 
+                   EnterWindowMask | LeaveWindowMask | PointerMotionMask,
+                   GrabModeAsync, GrabModeAsync,
+                   win, None, CurrentTime) == GrabSuccess) return 1;
+   return 0;
+}
+
+EAPI void
+ecore_x_pointer_ungrab(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XUngrabPointer(_ecore_x_disp, CurrentTime);
+}
+
+EAPI int
+ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y);
+}
+
+EAPI int
+ecore_x_keyboard_grab(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XGrabKeyboard(_ecore_x_disp, win, False,
+                    GrabModeAsync, GrabModeAsync,
+                    CurrentTime) == GrabSuccess) return 1;
+   return 0;
+}
+
+EAPI void
+ecore_x_keyboard_ungrab(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XUngrabKeyboard(_ecore_x_disp, CurrentTime);   
+}
+
+EAPI void
+ecore_x_grab(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_grab_count++;
+   if (_ecore_x_grab_count == 1) XGrabServer(_ecore_x_disp);
+}
+
+EAPI void
+ecore_x_ungrab(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_grab_count--;
+   if (_ecore_x_grab_count < 0) _ecore_x_grab_count = 0;
+   if (_ecore_x_grab_count == 0) XUngrabServer(_ecore_x_disp);
+}
+
+int      _ecore_window_grabs_num = 0;
+Window  *_ecore_window_grabs = NULL;
+int    (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event);
+void    *_ecore_window_grab_replay_data;
+
+EAPI void
+ecore_x_passive_grab_replay_func_set(int (*func) (void *data, int event_type, void *event), void *data)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_window_grab_replay_func = func;
+   _ecore_window_grab_replay_data = data;
+}
+
+EAPI void
+ecore_x_window_button_grab(Ecore_X_Window win, int button, 
+                          Ecore_X_Event_Mask event_mask,
+                          int mod, int any_mod)
+{
+   unsigned int        b;
+   unsigned int        m;
+   unsigned int        locks[8];
+   int                 i, ev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   b = button;
+   if (b == 0) b = AnyButton;
+   m = _ecore_x_event_modifier(mod);
+   if (any_mod) m = AnyModifier;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   ev = event_mask;
+   for (i = 0; i < 8; i++)
+     XGrabButton(_ecore_x_disp, b, m | locks[i],
+                win, False, ev, GrabModeSync, GrabModeAsync, None, None);
+   _ecore_window_grabs_num++;
+   _ecore_window_grabs = realloc(_ecore_window_grabs, 
+                                _ecore_window_grabs_num * sizeof(Window));
+   _ecore_window_grabs[_ecore_window_grabs_num - 1] = win;
+}
+
+void
+_ecore_x_sync_magic_send(int val, Ecore_X_Window swin)
+{
+   XEvent xev;
+   
+   xev.xclient.type = ClientMessage;
+   xev.xclient.serial = 0;
+   xev.xclient.send_event = True;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = _ecore_x_private_win;
+   xev.xclient.format = 32;
+   xev.xclient.message_type = 27777;
+   xev.xclient.data.l[0] = 0x7162534;
+   xev.xclient.data.l[1] = 0x10000000 + val;
+   xev.xclient.data.l[2] = swin;
+   XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev);
+}
+
+void
+_ecore_x_window_grab_remove(Ecore_X_Window win)
+{
+   int i, shuffle = 0;
+   
+   if (_ecore_window_grabs_num > 0)
+     {
+       for (i = 0; i < _ecore_window_grabs_num; i++)
+         {
+            if (shuffle) _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
+            if ((!shuffle) && (_ecore_window_grabs[i] == win))
+              shuffle = 1;
+         }
+       if (shuffle)
+         {
+            _ecore_window_grabs_num--;
+            _ecore_window_grabs = realloc(_ecore_window_grabs, 
+                                          _ecore_window_grabs_num * sizeof(Window));
+         }
+     }
+}
+
+EAPI void
+ecore_x_window_button_ungrab(Ecore_X_Window win, int button, 
+                            int mod, int any_mod)
+{
+   unsigned int        b;
+   unsigned int        m;
+   unsigned int        locks[8];
+   int                 i;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   b = button;
+   if (b == 0) b = AnyButton;
+   m = _ecore_x_event_modifier(mod);
+   if (any_mod) m = AnyModifier;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     XUngrabButton(_ecore_x_disp, b, m | locks[i], win);
+   _ecore_x_sync_magic_send(1, win);
+}
+
+int      _ecore_key_grabs_num = 0;
+Window  *_ecore_key_grabs = NULL;
+
+EAPI void
+ecore_x_window_key_grab(Ecore_X_Window win, const char *key, 
+                       int mod, int any_mod)
+{
+   KeyCode             keycode = 0;
+   KeySym              keysym;
+   unsigned int        m;
+   unsigned int        locks[8];
+   int                 i;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   else
+     {
+       keysym = XStringToKeysym(key);
+       if (keysym == NoSymbol) return;
+       keycode  = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
+     }
+   if (keycode == 0) return;
+   
+   m = _ecore_x_event_modifier(mod);
+   if (any_mod) m = AnyModifier;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     XGrabKey(_ecore_x_disp, keycode, m | locks[i],
+             win, False, GrabModeSync, GrabModeAsync);
+   _ecore_key_grabs_num++;
+   _ecore_key_grabs = realloc(_ecore_key_grabs,
+                             _ecore_key_grabs_num * sizeof(Window));
+   _ecore_key_grabs[_ecore_key_grabs_num - 1] = win;
+}
+
+void
+_ecore_x_key_grab_remove(Ecore_X_Window win)
+{
+   int i, shuffle = 0;
+   
+   if (_ecore_key_grabs_num > 0)
+     {
+       for (i = 0; i < _ecore_key_grabs_num; i++)
+         {
+            if (shuffle) _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
+            if ((!shuffle) && (_ecore_key_grabs[i] == win))
+              shuffle = 1;
+         }
+       if (shuffle)
+         {
+            _ecore_key_grabs_num--;
+            _ecore_key_grabs = realloc(_ecore_key_grabs, 
+                                       _ecore_key_grabs_num * sizeof(Window));
+         }
+     }
+}
+
+EAPI void
+ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key,
+                         int mod, int any_mod)
+{
+   KeyCode             keycode = 0;
+   KeySym              keysym;
+   unsigned int        m;
+   unsigned int        locks[8];
+   int                 i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   else
+     {
+       keysym = XStringToKeysym(key);
+       if (keysym == NoSymbol) return;
+       keycode  = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
+     }
+   if (keycode == 0) return;
+   
+   m = _ecore_x_event_modifier(mod);
+   if (any_mod) m = AnyModifier;
+   locks[0] = 0;
+   locks[1] = ECORE_X_LOCK_CAPS;
+   locks[2] = ECORE_X_LOCK_NUM;
+   locks[3] = ECORE_X_LOCK_SCROLL;
+   locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
+   locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
+   locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
+   for (i = 0; i < 8; i++)
+     XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win);
+   _ecore_x_sync_magic_send(2, win);
+}
+
+/**
+ * Send client message with given type and format 32.
+ *
+ * @param win     The window the message is sent to.
+ * @param type    The client message type.
+ * @param d0      The client message data item 1
+ * @param d1      The client message data item 2
+ * @param d2      The client message data item 3
+ * @param d3      The client message data item 4
+ * @param d4      The client message data item 5
+ *
+ * @return !0 on success.
+ */
+EAPI int
+ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type,
+                             Ecore_X_Event_Mask mask,
+                             long d0, long d1, long d2, long d3, long d4)
+{
+   XEvent xev;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.window = win;
+   xev.xclient.type = ClientMessage;
+   xev.xclient.message_type = type;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = d0;
+   xev.xclient.data.l[1] = d1;
+   xev.xclient.data.l[2] = d2;
+   xev.xclient.data.l[3] = d3;
+   xev.xclient.data.l[4] = d4;
+   
+   return XSendEvent(_ecore_x_disp, win, False, mask, &xev);
+}
+
+/**
+ * Send client message with given type and format 8.
+ *
+ * @param win     The window the message is sent to.
+ * @param type    The client message type.
+ * @param data    Data to be sent.
+ * @param len     Number of data bytes, max 20.
+ *
+ * @return !0 on success.
+ */
+EAPI int
+ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
+                            const void *data, int len)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.window = win;
+   xev.xclient.type = ClientMessage;
+   xev.xclient.message_type = type;
+   xev.xclient.format = 8;
+   if (len > 20) len = 20;
+   memcpy(xev.xclient.data.b, data, len);
+   memset(xev.xclient.data.b + len, 0, 20 - len);
+   
+   return XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
+}
+
+EAPI int
+ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
+{
+   XEvent xev;
+   XWindowAttributes att;
+   Window tw;
+   int rx, ry;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetWindowAttributes(_ecore_x_disp, win, &att);
+   XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
+   xev.xmotion.type = MotionNotify;
+   xev.xmotion.window = win;
+   xev.xmotion.root = att.root;
+   xev.xmotion.subwindow = win;
+   xev.xmotion.time = _ecore_x_event_last_time;
+   xev.xmotion.x = x;
+   xev.xmotion.y = y;
+   xev.xmotion.x_root = rx;
+   xev.xmotion.y_root = ry;
+   xev.xmotion.state = 0;
+   xev.xmotion.is_hint = 0;
+   xev.xmotion.same_screen = 1;
+   return XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev);
+}
+
+EAPI int
+ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
+{
+   XEvent xev;
+   XWindowAttributes att;
+   Window tw;
+   int rx, ry;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetWindowAttributes(_ecore_x_disp, win, &att);
+   XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
+   xev.xbutton.type = ButtonPress;
+   xev.xbutton.window = win;
+   xev.xbutton.root = att.root;
+   xev.xbutton.subwindow = win;
+   xev.xbutton.time = _ecore_x_event_last_time;
+   xev.xbutton.x = x;
+   xev.xbutton.y = y;
+   xev.xbutton.x_root = rx;
+   xev.xbutton.y_root = ry;
+   xev.xbutton.state = 1 << b;
+   xev.xbutton.button = b;
+   xev.xbutton.same_screen = 1;
+   return XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev);
+}
+
+EAPI int
+ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
+{
+   XEvent xev;
+   XWindowAttributes att;
+   Window tw;
+   int rx, ry;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetWindowAttributes(_ecore_x_disp, win, &att);
+   XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
+   xev.xbutton.type = ButtonRelease;
+   xev.xbutton.window = win;
+   xev.xbutton.root = att.root;
+   xev.xbutton.subwindow = win;
+   xev.xbutton.time = _ecore_x_event_last_time;
+   xev.xbutton.x = x;
+   xev.xbutton.y = y;
+   xev.xbutton.x_root = rx;
+   xev.xbutton.y_root = ry;
+   xev.xbutton.state = 0;
+   xev.xbutton.button = b;
+   xev.xbutton.same_screen = 1;
+   return XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev);
+}
+
+EAPI void
+ecore_x_focus_reset(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime);
+}
+
+EAPI void
+ecore_x_events_allow_all(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime);
+}
+
+EAPI void
+ecore_x_pointer_last_xy_get(int *x, int *y)
+{
+   if (x) *x = _ecore_x_event_last_root_x;
+   if (y) *y = _ecore_x_event_last_root_y;
+}
+
+EAPI void
+ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
+{
+   Window rwin, cwin;
+   int rx, ry, wx, wy, ret;
+   unsigned int mask;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = XQueryPointer(_ecore_x_disp, win, &rwin, &cwin, &rx, &ry, &wx, &wy, &mask);
+   if (!ret) wx = wy = -1;
+   if (x) *x = wx;
+   if (y) *y = wy;
+}
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+static int
+_ecore_x_event_modifier(unsigned int state)
+{
+   int xmodifiers = 0;
+
+   if (state & ECORE_EVENT_MODIFIER_SHIFT) xmodifiers |= ECORE_X_MODIFIER_SHIFT;
+   if (state & ECORE_EVENT_MODIFIER_CTRL) xmodifiers |= ECORE_X_MODIFIER_CTRL;
+   if (state & ECORE_EVENT_MODIFIER_ALT) xmodifiers |= ECORE_X_MODIFIER_ALT;
+   if (state & ECORE_EVENT_MODIFIER_WIN) xmodifiers |= ECORE_X_MODIFIER_WIN;
+   if (state & ECORE_EVENT_LOCK_SCROLL) xmodifiers |= ECORE_X_LOCK_SCROLL;
+   if (state & ECORE_EVENT_LOCK_NUM) xmodifiers |= ECORE_X_LOCK_NUM;
+   if (state & ECORE_EVENT_LOCK_CAPS) xmodifiers |= ECORE_X_LOCK_CAPS;
+
+   return xmodifiers;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_atoms.c b/src/lib/ecore_x/xlib/ecore_x_atoms.c
new file mode 100644 (file)
index 0000000..c7b2ea2
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# include <stddef.h>
+# ifdef  __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+#include "ecore_x_atoms_decl.h"
+
+typedef struct
+{
+   const char   *name;
+   Ecore_X_Atom *atom;
+} Atom_Item;
+
+void
+_ecore_x_atoms_init(void)
+{
+   const Atom_Item items[] =
+     {
+       { "ATOM", &ECORE_X_ATOM_ATOM },
+       { "CARDINAL", &ECORE_X_ATOM_CARDINAL },
+       { "COMPOUND_TEXT", &ECORE_X_ATOM_COMPOUND_TEXT },
+       { "FILE_NAME", &ECORE_X_ATOM_FILE_NAME },
+       { "STRING", &ECORE_X_ATOM_STRING },
+       { "TEXT", &ECORE_X_ATOM_TEXT },
+       { "UTF8_STRING", &ECORE_X_ATOM_UTF8_STRING },
+       { "WINDOW", &ECORE_X_ATOM_WINDOW },
+
+       { "JXSelectionWindowProperty", &ECORE_X_ATOM_SELECTION_PROP_XDND },
+       { "XdndSelection", &ECORE_X_ATOM_SELECTION_XDND },
+       { "XdndAware", &ECORE_X_ATOM_XDND_AWARE },
+       { "XdndEnter", &ECORE_X_ATOM_XDND_ENTER },
+       { "XdndTypeList", &ECORE_X_ATOM_XDND_TYPE_LIST },
+       { "XdndPosition", &ECORE_X_ATOM_XDND_POSITION },
+       { "XdndActionCopy", &ECORE_X_ATOM_XDND_ACTION_COPY },
+       { "XdndActionMove", &ECORE_X_ATOM_XDND_ACTION_MOVE },
+       { "XdndActionPrivate", &ECORE_X_ATOM_XDND_ACTION_PRIVATE },
+       { "XdndActionAsk", &ECORE_X_ATOM_XDND_ACTION_ASK },
+       { "XdndActionList", &ECORE_X_ATOM_XDND_ACTION_LIST },
+       { "XdndActionLink", &ECORE_X_ATOM_XDND_ACTION_LINK },
+       { "XdndActionDescription", &ECORE_X_ATOM_XDND_ACTION_DESCRIPTION },
+       { "XdndProxy", &ECORE_X_ATOM_XDND_PROXY },
+       { "XdndStatus", &ECORE_X_ATOM_XDND_STATUS },
+       { "XdndLeave", &ECORE_X_ATOM_XDND_LEAVE },
+       { "XdndDrop", &ECORE_X_ATOM_XDND_DROP },
+       { "XdndFinished", &ECORE_X_ATOM_XDND_FINISHED },
+
+       { "XdndActionCopy", &ECORE_X_DND_ACTION_COPY },
+       { "XdndActionMove", &ECORE_X_DND_ACTION_MOVE },
+       { "XdndActionLink", &ECORE_X_DND_ACTION_LINK },
+       { "XdndActionAsk", &ECORE_X_DND_ACTION_ASK },
+       { "XdndActionPrivate", &ECORE_X_DND_ACTION_PRIVATE },
+
+       { "_E_FRAME_SIZE", &ECORE_X_ATOM_E_FRAME_SIZE },
+
+       { "_WIN_LAYER", &ECORE_X_ATOM_WIN_LAYER },
+
+       { "WM_NAME", &ECORE_X_ATOM_WM_NAME },
+       { "WM_ICON_NAME", &ECORE_X_ATOM_WM_ICON_NAME },
+       { "WM_NORMAL_HINTS", &ECORE_X_ATOM_WM_NORMAL_HINTS },
+       { "WM_SIZE_HINTS", &ECORE_X_ATOM_WM_SIZE_HINTS },
+       { "WM_HINTS", &ECORE_X_ATOM_WM_HINTS },
+       { "WM_CLASS", &ECORE_X_ATOM_WM_CLASS },
+       { "WM_TRANSIENT_FOR", &ECORE_X_ATOM_WM_TRANSIENT_FOR },
+       { "WM_PROTOCOLS", &ECORE_X_ATOM_WM_PROTOCOLS },
+       { "WM_COLORMAP_WINDOWS", &ECORE_X_ATOM_WM_COLORMAP_WINDOWS },
+       { "WM_COMMAND", &ECORE_X_ATOM_WM_COMMAND },
+       { "WM_CLIENT_MACHINE", &ECORE_X_ATOM_WM_CLIENT_MACHINE },
+
+       { "WM_STATE", &ECORE_X_ATOM_WM_STATE },
+       { "WM_ICON_SIZE", &ECORE_X_ATOM_WM_ICON_SIZE },
+
+       { "WM_CHANGE_STATE", &ECORE_X_ATOM_WM_CHANGE_STATE },
+
+       { "WM_TAKE_FOCUS", &ECORE_X_ATOM_WM_TAKE_FOCUS },
+       { "WM_SAVE_YOURSELF", &ECORE_X_ATOM_WM_SAVE_YOURSELF },
+       { "WM_DELETE_WINDOW", &ECORE_X_ATOM_WM_DELETE_WINDOW },
+
+       { "WM_COLORMAP_NOTIFY", &ECORE_X_ATOM_WM_COLORMAP_NOTIFY },
+
+       { "SM_CLIENT_ID", &ECORE_X_ATOM_SM_CLIENT_ID },
+       { "WM_CLIENT_LEADER", &ECORE_X_ATOM_WM_CLIENT_LEADER },
+       { "WM_WINDOW_ROLE", &ECORE_X_ATOM_WM_WINDOW_ROLE },
+
+       { "_MOTIF_WM_HINTS", &ECORE_X_ATOM_MOTIF_WM_HINTS },
+
+       { "_NET_SUPPORTED", &ECORE_X_ATOM_NET_SUPPORTED },
+       { "_NET_CLIENT_LIST", &ECORE_X_ATOM_NET_CLIENT_LIST },
+       { "_NET_CLIENT_LIST_STACKING", &ECORE_X_ATOM_NET_CLIENT_LIST_STACKING },
+       { "_NET_NUMBER_OF_DESKTOPS", &ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS },
+       { "_NET_DESKTOP_GEOMETRY", &ECORE_X_ATOM_NET_DESKTOP_GEOMETRY },
+       { "_NET_DESKTOP_VIEWPORT", &ECORE_X_ATOM_NET_DESKTOP_VIEWPORT },
+       { "_NET_CURRENT_DESKTOP", &ECORE_X_ATOM_NET_CURRENT_DESKTOP },
+       { "_NET_DESKTOP_NAMES", &ECORE_X_ATOM_NET_DESKTOP_NAMES },
+       { "_NET_ACTIVE_WINDOW", &ECORE_X_ATOM_NET_ACTIVE_WINDOW },
+       { "_NET_WORKAREA", &ECORE_X_ATOM_NET_WORKAREA },
+       { "_NET_SUPPORTING_WM_CHECK", &ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK },
+       { "_NET_VIRTUAL_ROOTS", &ECORE_X_ATOM_NET_VIRTUAL_ROOTS },
+       { "_NET_DESKTOP_LAYOUT", &ECORE_X_ATOM_NET_DESKTOP_LAYOUT },
+       { "_NET_SHOWING_DESKTOP", &ECORE_X_ATOM_NET_SHOWING_DESKTOP },
+
+       { "_NET_CLOSE_WINDOW", &ECORE_X_ATOM_NET_CLOSE_WINDOW },
+       { "_NET_MOVERESIZE_WINDOW", &ECORE_X_ATOM_NET_MOVERESIZE_WINDOW },
+       { "_NET_WM_MOVERESIZE", &ECORE_X_ATOM_NET_WM_MOVERESIZE },
+       { "_NET_RESTACK_WINDOW", &ECORE_X_ATOM_NET_RESTACK_WINDOW },
+
+       { "_NET_REQUEST_FRAME_EXTENTS", &ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS },
+
+       { "_NET_WM_NAME", &ECORE_X_ATOM_NET_WM_NAME },
+       { "_NET_WM_VISIBLE_NAME", &ECORE_X_ATOM_NET_WM_VISIBLE_NAME },
+       { "_NET_WM_ICON_NAME", &ECORE_X_ATOM_NET_WM_ICON_NAME },
+       { "_NET_WM_VISIBLE_ICON_NAME", &ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME },
+       { "_NET_WM_DESKTOP", &ECORE_X_ATOM_NET_WM_DESKTOP },
+
+       { "_NET_WM_WINDOW_TYPE", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE },
+       { "_NET_WM_WINDOW_TYPE_DESKTOP", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP },
+       { "_NET_WM_WINDOW_TYPE_DOCK", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK },
+       { "_NET_WM_WINDOW_TYPE_TOOLBAR", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR },
+       { "_NET_WM_WINDOW_TYPE_MENU", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU },
+       { "_NET_WM_WINDOW_TYPE_UTILITY", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY },
+       { "_NET_WM_WINDOW_TYPE_SPLASH", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH },
+       { "_NET_WM_WINDOW_TYPE_DIALOG", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG },
+       { "_NET_WM_WINDOW_TYPE_NORMAL", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL },
+       { "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU },
+       { "_NET_WM_WINDOW_TYPE_POPUP_MENU", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU },
+       { "_NET_WM_WINDOW_TYPE_TOOLTIP", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP },
+       { "_NET_WM_WINDOW_TYPE_NOTIFICATION", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION },
+       { "_NET_WM_WINDOW_TYPE_COMBO", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO },
+       { "_NET_WM_WINDOW_TYPE_DND", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND },
+
+       { "_NET_WM_STATE", &ECORE_X_ATOM_NET_WM_STATE },
+       { "_NET_WM_STATE_MODAL", &ECORE_X_ATOM_NET_WM_STATE_MODAL },
+       { "_NET_WM_STATE_STICKY", &ECORE_X_ATOM_NET_WM_STATE_STICKY },
+       { "_NET_WM_STATE_MAXIMIZED_VERT", &ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT },
+       { "_NET_WM_STATE_MAXIMIZED_HORZ", &ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ },
+       { "_NET_WM_STATE_SHADED", &ECORE_X_ATOM_NET_WM_STATE_SHADED },
+       { "_NET_WM_STATE_SKIP_TASKBAR", &ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR },
+       { "_NET_WM_STATE_SKIP_PAGER", &ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER },
+       { "_NET_WM_STATE_HIDDEN", &ECORE_X_ATOM_NET_WM_STATE_HIDDEN },
+       { "_NET_WM_STATE_FULLSCREEN", &ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN },
+       { "_NET_WM_STATE_ABOVE", &ECORE_X_ATOM_NET_WM_STATE_ABOVE },
+       { "_NET_WM_STATE_BELOW", &ECORE_X_ATOM_NET_WM_STATE_BELOW },
+       { "_NET_WM_STATE_DEMANDS_ATTENTION", &ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION },
+
+       { "_NET_WM_ALLOWED_ACTIONS", &ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS },
+       { "_NET_WM_ACTION_MOVE", &ECORE_X_ATOM_NET_WM_ACTION_MOVE },
+       { "_NET_WM_ACTION_RESIZE", &ECORE_X_ATOM_NET_WM_ACTION_RESIZE },
+       { "_NET_WM_ACTION_MINIMIZE", &ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE },
+       { "_NET_WM_ACTION_SHADE", &ECORE_X_ATOM_NET_WM_ACTION_SHADE },
+       { "_NET_WM_ACTION_STICK", &ECORE_X_ATOM_NET_WM_ACTION_STICK },
+       { "_NET_WM_ACTION_MAXIMIZE_HORZ", &ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ },
+       { "_NET_WM_ACTION_MAXIMIZE_VERT", &ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT },
+       { "_NET_WM_ACTION_FULLSCREEN", &ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN },
+       { "_NET_WM_ACTION_CHANGE_DESKTOP", &ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP },
+       { "_NET_WM_ACTION_CLOSE", &ECORE_X_ATOM_NET_WM_ACTION_CLOSE },
+       { "_NET_WM_ACTION_ABOVE", &ECORE_X_ATOM_NET_WM_ACTION_ABOVE },
+       { "_NET_WM_ACTION_BELOW", &ECORE_X_ATOM_NET_WM_ACTION_BELOW },
+
+       { "_NET_WM_STRUT", &ECORE_X_ATOM_NET_WM_STRUT },
+       { "_NET_WM_STRUT_PARTIAL", &ECORE_X_ATOM_NET_WM_STRUT_PARTIAL },
+       { "_NET_WM_ICON_GEOMETRY", &ECORE_X_ATOM_NET_WM_ICON_GEOMETRY },
+       { "_NET_WM_ICON", &ECORE_X_ATOM_NET_WM_ICON },
+       { "_NET_WM_PID", &ECORE_X_ATOM_NET_WM_PID },
+       { "_NET_WM_HANDLED_ICONS", &ECORE_X_ATOM_NET_WM_HANDLED_ICONS },
+       { "_NET_WM_USER_TIME", &ECORE_X_ATOM_NET_WM_USER_TIME },
+       { "_NET_STARTUP_ID", &ECORE_X_ATOM_NET_STARTUP_ID },
+       { "_NET_FRAME_EXTENTS", &ECORE_X_ATOM_NET_FRAME_EXTENTS },
+
+       { "_NET_WM_PING", &ECORE_X_ATOM_NET_WM_PING },
+       { "_NET_WM_SYNC_REQUEST", &ECORE_X_ATOM_NET_WM_SYNC_REQUEST },
+       { "_NET_WM_SYNC_REQUEST_COUNTER", &ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER },
+
+       { "_NET_WM_WINDOW_OPACITY", &ECORE_X_ATOM_NET_WM_WINDOW_OPACITY },
+       { "_NET_WM_WINDOW_SHADOW", &ECORE_X_ATOM_NET_WM_WINDOW_SHADOW },
+       { "_NET_WM_WINDOW_SHADE", &ECORE_X_ATOM_NET_WM_WINDOW_SHADE },
+
+       { "TARGETS", &ECORE_X_ATOM_SELECTION_TARGETS },
+       { "CLIPBOARD", &ECORE_X_ATOM_SELECTION_CLIPBOARD },
+       { "PRIMARY", &ECORE_X_ATOM_SELECTION_PRIMARY },
+       { "SECONDARY", &ECORE_X_ATOM_SELECTION_SECONDARY },
+       { "_ECORE_SELECTION_PRIMARY", &ECORE_X_ATOM_SELECTION_PROP_PRIMARY },
+       { "_ECORE_SELECTION_SECONDARY", &ECORE_X_ATOM_SELECTION_PROP_SECONDARY },
+       { "_ECORE_SELECTION_CLIPBOARD", &ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD },
+
+       { "_E_VIRTUAL_KEYBOARD", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD },
+       { "_E_VIRTUAL_KEYBOARD_STATE", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE },
+       { "_E_VIRTUAL_KEYBOARD_ON", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON },
+       { "_E_VIRTUAL_KEYBOARD_OFF", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF },
+       { "_E_VIRTUAL_KEYBOARD_ALPHA", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA },
+       { "_E_VIRTUAL_KEYBOARD_NUMERIC", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC },
+       { "_E_VIRTUAL_KEYBOARD_PIN", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN },
+       { "_E_VIRTUAL_KEYBOARD_PHONE_NUMBER", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER },
+       { "_E_VIRTUAL_KEYBOARD_HEX", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX },
+       { "_E_VIRTUAL_KEYBOARD_TERMINAL", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL },
+       { "_E_VIRTUAL_KEYBOARD_PASSWORD", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD }, 
+       { "_E_VIRTUAL_KEYBOARD_IP", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP }, 
+       { "_E_VIRTUAL_KEYBOARD_HOST", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST }, 
+       { "_E_VIRTUAL_KEYBOARD_FILE", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE }, 
+       { "_E_VIRTUAL_KEYBOARD_URL", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL }, 
+       { "_E_VIRTUAL_KEYBOARD_KEYPAD", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD }, 
+       { "_E_VIRTUAL_KEYBOARD_J2ME", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME }, 
+
+        { "_E_ILLUME_ZONE", &ECORE_X_ATOM_E_ILLUME_ZONE }, 
+        { "_E_ILLUME_ZONE_LIST", &ECORE_X_ATOM_E_ILLUME_ZONE_LIST }, 
+        { "_E_ILLUME_CONFORMANT", &ECORE_X_ATOM_E_ILLUME_CONFORMANT }, 
+        { "_E_ILLUME_MODE", &ECORE_X_ATOM_E_ILLUME_MODE }, 
+        { "_E_ILLUME_MODE_SINGLE", &ECORE_X_ATOM_E_ILLUME_MODE_SINGLE }, 
+        { "_E_ILLUME_MODE_DUAL_TOP", &ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP }, 
+        { "_E_ILLUME_MODE_DUAL_LEFT", &ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT }, 
+        { "_E_ILLUME_FOCUS_BACK", &ECORE_X_ATOM_E_ILLUME_FOCUS_BACK }, 
+        { "_E_ILLUME_FOCUS_FORWARD", &ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD }, 
+        { "_E_ILLUME_FOCUS_HOME", &ECORE_X_ATOM_E_ILLUME_FOCUS_HOME }, 
+        { "_E_ILLUME_CLOSE", &ECORE_X_ATOM_E_ILLUME_CLOSE }, 
+        { "_E_ILLUME_HOME_NEW", &ECORE_X_ATOM_E_ILLUME_HOME_NEW }, 
+        { "_E_ILLUME_HOME_DEL", &ECORE_X_ATOM_E_ILLUME_HOME_DEL }, 
+        { "_E_ILLUME_DRAG", &ECORE_X_ATOM_E_ILLUME_DRAG }, 
+        { "_E_ILLUME_DRAG_LOCKED", &ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED }, 
+        { "_E_ILLUME_DRAG_START", &ECORE_X_ATOM_E_ILLUME_DRAG_START }, 
+        { "_E_ILLUME_DRAG_END", &ECORE_X_ATOM_E_ILLUME_DRAG_END }, 
+        { "_E_ILLUME_INDICATOR_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY }, 
+        { "_E_ILLUME_SOFTKEY_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY },
+        { "_E_ILLUME_KEYBOARD_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY },
+        { "_E_ILLUME_QUICKPANEL", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL }, 
+        { "_E_ILLUME_QUICKPANEL_STATE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE }, 
+        { "_E_ILLUME_QUICKPANEL_STATE_TOGGLE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE }, 
+        { "_E_ILLUME_QUICKPANEL_ON", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON }, 
+        { "_E_ILLUME_QUICKPANEL_OFF", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF }, 
+        { "_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR }, 
+        { "_E_ILLUME_QUICKPANEL_PRIORITY_MINOR", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR }, 
+        { "_E_ILLUME_QUICKPANEL_ZONE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE }, 
+        { "_E_ILLUME_QUICKPANEL_POSITION_UPDATE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE }, 
+
+        { "_E_COMP_SYNC_COUNTER", &ECORE_X_ATOM_E_COMP_SYNC_COUNTER },
+        { "_E_COMP_SYNC_DRAW_DONE", &ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE },
+        { "_E_COMP_SYNC_SUPPORTED", &ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED },
+        { "_E_COMP_SYNC_BEGIN", &ECORE_X_ATOM_E_COMP_SYNC_BEGIN },
+        { "_E_COMP_SYNC_END", &ECORE_X_ATOM_E_COMP_SYNC_END },
+        { "_E_COMP_SYNC_CANCEL", &ECORE_X_ATOM_E_COMP_SYNC_CANCEL },
+        
+        { "_E_COMP_FLUSH", &ECORE_X_ATOM_E_COMP_FLUSH },
+        { "_E_COMP_DUMP", &ECORE_X_ATOM_E_COMP_DUMP }
+     };
+   Atom *atoms;
+   char **names;
+   int i, num;
+
+   num = sizeof(items) / sizeof(Atom_Item);
+   atoms = alloca(num * sizeof(Atom));
+   names = alloca(num * sizeof(char *));
+   for (i = 0; i < num; i++) names[i] = (char *)items[i].name;
+   XInternAtoms(_ecore_x_disp, names, num, False, atoms);
+   for (i = 0; i < num; i++) *(items[i].atom) = atoms[i];
+}
+
+/**
+ * Retrieves the atom value associated with the given name.
+ * @param  name The given name.
+ * @return Associated atom value.
+ */
+EAPI Ecore_X_Atom
+ecore_x_atom_get(const char *name)
+{
+   if (!_ecore_x_disp) return 0;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XInternAtom(_ecore_x_disp, name, False);
+}
+
+EAPI void
+ecore_x_atoms_get(const char **names, int num, Ecore_X_Atom *atoms)
+{
+   Atom *atoms_int;
+   int i;
+
+   if (!_ecore_x_disp) return;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atoms_int = alloca(num * sizeof(Atom));
+   XInternAtoms(_ecore_x_disp, (char **)names, num, False, atoms_int);
+   for (i = 0; i < num; i++)
+     atoms[i] = atoms_int[i];
+}
+
+EAPI char *
+ecore_x_atom_name_get(Ecore_X_Atom atom)
+{
+   char *name;
+   char *xname;
+
+   if (!_ecore_x_disp) return NULL;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   xname = XGetAtomName(_ecore_x_disp, atom);
+   if (!xname) return NULL;
+
+   name = strdup(xname);
+   XFree(xname);
+
+   return name;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_composite.c b/src/lib/ecore_x/xlib/ecore_x_composite.c
new file mode 100644 (file)
index 0000000..617f0fb
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+static int _composite_available;
+
+void
+_ecore_x_composite_init(void)
+{
+   _composite_available = 0;
+
+#ifdef ECORE_XCOMPOSITE
+   int major, minor;
+
+   if (XCompositeQueryVersion(_ecore_x_disp, &major, &minor))
+     _composite_available = 1;
+#endif
+}
+
+EAPI int
+ecore_x_composite_query(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _composite_available;
+}
+
+EAPI void
+ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type)
+{
+#ifdef ECORE_XCOMPOSITE
+   int update = CompositeRedirectAutomatic;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   switch(type)
+     {
+      case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC:
+        update = CompositeRedirectAutomatic;
+        break;
+      case ECORE_X_COMPOSITE_UPDATE_MANUAL:
+        update = CompositeRedirectManual;
+        break;
+     }
+   XCompositeRedirectWindow(_ecore_x_disp, win, update);
+#endif
+}
+
+EAPI void
+ecore_x_composite_redirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type)
+{
+#ifdef ECORE_XCOMPOSITE
+   int update = CompositeRedirectAutomatic;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   switch(type)
+     {
+      case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC:
+        update = CompositeRedirectAutomatic;
+        break;
+      case ECORE_X_COMPOSITE_UPDATE_MANUAL:
+        update = CompositeRedirectManual;
+        break;
+     }
+   XCompositeRedirectSubwindows(_ecore_x_disp, win, update);
+#endif
+}
+
+EAPI void
+ecore_x_composite_unredirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type)
+{
+#ifdef ECORE_XCOMPOSITE
+   int update = CompositeRedirectAutomatic;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   switch(type)
+     {
+      case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC:
+        update = CompositeRedirectAutomatic;
+        break;
+      case ECORE_X_COMPOSITE_UPDATE_MANUAL:
+        update = CompositeRedirectManual;
+        break;
+     }
+   XCompositeUnredirectWindow(_ecore_x_disp, win, update);
+#endif
+}
+
+EAPI void
+ecore_x_composite_unredirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type)
+{
+#ifdef ECORE_XCOMPOSITE
+   int update = CompositeRedirectAutomatic;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   switch(type)
+     {
+      case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC:
+        update = CompositeRedirectAutomatic;
+        break;
+      case ECORE_X_COMPOSITE_UPDATE_MANUAL:
+        update = CompositeRedirectManual;
+        break;
+     }
+   XCompositeUnredirectSubwindows(_ecore_x_disp, win, update);
+#endif
+}
+
+EAPI Ecore_X_Pixmap
+ecore_x_composite_name_window_pixmap_get(Ecore_X_Window win)
+{
+   Ecore_X_Pixmap pixmap = None;
+  
+#ifdef ECORE_XCOMPOSITE
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   pixmap = XCompositeNameWindowPixmap(_ecore_x_disp, win);
+#endif
+
+   return pixmap;
+}
+
+EAPI Ecore_X_Window
+ecore_x_composite_render_window_enable(Ecore_X_Window root)
+{
+   Ecore_X_Window win = 0;
+#ifdef ECORE_XCOMPOSITE
+   XRectangle rect;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   win = XCompositeGetOverlayWindow(_ecore_x_disp, root);
+   rect.x = -1;
+   rect.y = -1;
+   rect.width = 1;
+   rect.height = 1;
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeInput, 0, 0, &rect, 1, 
+                           ShapeSet, Unsorted);
+#endif
+   return win;
+}
+
+EAPI void
+ecore_x_composite_render_window_disable(Ecore_X_Window root)
+{
+#ifdef ECORE_XCOMPOSITE
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XCompositeReleaseOverlayWindow(_ecore_x_disp, root);
+#endif   
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_cursor.c b/src/lib/ecore_x/xlib/ecore_x_cursor.c
new file mode 100644 (file)
index 0000000..82c50a0
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "ecore_x_private.h"
+
+
+EAPI int
+ecore_x_cursor_color_supported_get(void)
+{
+   return _ecore_x_xcursor;
+}
+
+EAPI Ecore_X_Cursor
+ecore_x_cursor_new(Ecore_X_Window win, int *pixels, int w, int h, int hot_x, int hot_y)
+{
+#ifdef ECORE_XCURSOR
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (_ecore_x_xcursor)
+     {
+       Cursor c;
+       XcursorImage *xci;
+
+       xci = XcursorImageCreate(w, h);
+       if (xci)
+         {
+            int i;
+
+            xci->xhot = hot_x;
+            xci->yhot = hot_y;
+            xci->delay = 0;
+            for (i = 0; i < (w * h); i++)
+              {
+//               int r, g, b, a;
+//
+//               a = (pixels[i] >> 24) & 0xff;
+//               r = (((pixels[i] >> 16) & 0xff) * a) / 0xff;
+//               g = (((pixels[i] >> 8 ) & 0xff) * a) / 0xff;
+//               b = (((pixels[i]      ) & 0xff) * a) / 0xff;
+                 xci->pixels[i] = pixels[i];
+//                 (a << 24) | (r << 16) | (g << 8) | (b);
+              }
+            c = XcursorImageLoadCursor(_ecore_x_disp, xci);
+            XcursorImageDestroy(xci);
+            return c;
+         }
+     }
+   else
+#endif
+     {
+       XColor c1, c2;
+       Cursor c;
+       Pixmap pmap, mask;
+       GC gc;
+       XGCValues gcv;
+       XImage *xim;
+       unsigned int *pix;
+       int fr, fg, fb, br, bg, bb;
+       int brightest = 0;
+       int darkest = 255 * 3;
+       int x, y;
+       const int dither[2][2] =
+         {
+              {0, 2},
+              {3, 1}
+         };
+
+       pmap = XCreatePixmap(_ecore_x_disp, win, w, h, 1);
+       mask = XCreatePixmap(_ecore_x_disp, win, w, h, 1);
+       xim = XCreateImage(_ecore_x_disp,
+                          DefaultVisual(_ecore_x_disp, 0),
+                          1, ZPixmap, 0, NULL, w, h, 32, 0);
+       xim->data = malloc(xim->bytes_per_line * xim->height);
+
+       fr = 0x00; fg = 0x00; fb = 0x00;
+       br = 0xff; bg = 0xff; bb = 0xff;
+       pix = (unsigned int*)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 int r, g, b, a;
+
+                 a = (pix[0] >> 24) & 0xff;
+                 r = (pix[0] >> 16) & 0xff;
+                 g = (pix[0] >> 8 ) & 0xff;
+                 b = (pix[0]      ) & 0xff;
+                 if (a > 0)
+                   {
+                      if ((r + g + b) > brightest)
+                        {
+                           brightest = r + g + b;
+                           br = r;
+                           bg = g;
+                           bb = b;
+                        }
+                      if ((r + g + b) < darkest)
+                        {
+                           darkest = r + g + b;
+                           fr = r;
+                           fg = g;
+                           fb = b;
+                        }
+                   }
+                 pix++;
+              }
+         }
+
+       pix = (unsigned int*)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 int v;
+                 int r, g, b;
+                 int d1, d2;
+
+                 r = (pix[0] >> 16) & 0xff;
+                 g = (pix[0] >> 8 ) & 0xff;
+                 b = (pix[0]      ) & 0xff;
+                 d1 =
+                   ((r - fr) * (r - fr)) +
+                   ((g - fg) * (g - fg)) +
+                   ((b - fb) * (b - fb));
+                 d2 =
+                   ((r - br) * (r - br)) +
+                   ((g - bg) * (g - bg)) +
+                   ((b - bb) * (b - bb));
+                 if (d1 + d2)
+                   {
+                      v = (((d2 * 255) / (d1 + d2)) * 5) / 256;
+                      if (v > dither[x & 0x1][y & 0x1]) v = 1;
+                      else v = 0;
+                   }
+                 else
+                   {
+                      v = 0;
+                   }
+                 XPutPixel(xim, x, y, v);
+                 pix++;
+              }
+         }
+       gc = XCreateGC(_ecore_x_disp, pmap, 0, &gcv);
+       XPutImage(_ecore_x_disp, pmap, gc, xim, 0, 0, 0, 0, w, h);
+       XFreeGC(_ecore_x_disp, gc);
+
+       pix = (unsigned int*)pixels;
+       for (y = 0; y < h; y++)
+         {
+            for (x = 0; x < w; x++)
+              {
+                 int v;
+
+                 v = (((pix[0] >> 24) & 0xff) * 5) / 256;
+                 if (v > dither[x & 0x1][y & 0x1]) v = 1;
+                 else v = 0;
+                 XPutPixel(xim, x, y, v);
+                 pix++;
+              }
+         }
+       gc = XCreateGC(_ecore_x_disp, mask, 0, &gcv);
+       XPutImage(_ecore_x_disp, mask, gc, xim, 0, 0, 0, 0, w, h);
+       XFreeGC(_ecore_x_disp, gc);
+
+       free(xim->data);
+       xim->data = NULL;
+       XDestroyImage(xim);
+
+       c1.pixel = 0;
+       c1.red   = fr << 8 | fr;
+       c1.green = fg << 8 | fg;
+       c1.blue  = fb << 8 | fb;
+       c1.flags = DoRed | DoGreen | DoBlue;
+
+       c2.pixel = 0;
+       c2.red   = br << 8 | br;
+       c2.green = bg << 8 | bg;
+       c2.blue  = bb << 8 | bb;
+       c2.flags = DoRed | DoGreen | DoBlue;
+
+       c = XCreatePixmapCursor(_ecore_x_disp,
+                               pmap, mask,
+                               &c1, &c2,
+                               hot_x, hot_y);
+       XFreePixmap(_ecore_x_disp, pmap);
+       XFreePixmap(_ecore_x_disp, mask);
+       return c;
+     }
+   return 0;
+}
+
+EAPI void
+ecore_x_cursor_free(Ecore_X_Cursor c)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFreeCursor(_ecore_x_disp, c);
+}
+
+/*
+ * Returns the cursor for the given shape.
+ * Note that the return value must not be freed with
+ * ecore_x_cursor_free()!
+ */
+EAPI Ecore_X_Cursor
+ecore_x_cursor_shape_get(int shape)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* Shapes are defined in Ecore_X_Cursor.h */
+   return XCreateFontCursor(_ecore_x_disp, shape);
+}
+
+EAPI void
+ecore_x_cursor_size_set(int size)
+{
+#ifdef ECORE_XCURSOR
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XcursorSetDefaultSize(_ecore_x_disp, size);
+#else
+   size = 0;
+#endif
+}
+
+EAPI int
+ecore_x_cursor_size_get(void)
+{
+#ifdef ECORE_XCURSOR
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XcursorGetDefaultSize(_ecore_x_disp);
+#else
+   return 0;
+#endif
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_damage.c b/src/lib/ecore_x/xlib/ecore_x_damage.c
new file mode 100644 (file)
index 0000000..05695ec
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+static int _damage_available;
+#ifdef ECORE_XDAMAGE
+static int _damage_major, _damage_minor;
+#endif
+
+void
+_ecore_x_damage_init(void)
+{
+#ifdef ECORE_XDAMAGE
+   _damage_major = 1;
+   _damage_minor = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XDamageQueryVersion(_ecore_x_disp, &_damage_major, &_damage_minor))
+     _damage_available = 1;
+   else
+     _damage_available = 0;
+#else
+   _damage_available = 0;
+#endif
+}
+
+EAPI int
+ecore_x_damage_query(void)
+{
+   return _damage_available;
+}
+
+EAPI Ecore_X_Damage
+ecore_x_damage_new(Ecore_X_Drawable d, Ecore_X_Damage_Report_Level level)
+{
+#ifdef ECORE_XDAMAGE
+   Ecore_X_Damage damage;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   damage = XDamageCreate(_ecore_x_disp, d, level);
+   return damage;
+#else
+   return 0;
+#endif
+}
+
+EAPI void
+ecore_x_damage_free(Ecore_X_Damage damage)
+{
+#ifdef ECORE_XDAMAGE
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XDamageDestroy(_ecore_x_disp, damage);
+#endif
+}
+
+EAPI void
+ecore_x_damage_subtract(Ecore_X_Damage damage, Ecore_X_Region repair, Ecore_X_Region parts)
+{
+#ifdef ECORE_XDAMAGE
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XDamageSubtract(_ecore_x_disp, damage, repair, parts);
+#endif
+}
+
diff --git a/src/lib/ecore_x/xlib/ecore_x_dnd.c b/src/lib/ecore_x/xlib/ecore_x_dnd.c
new file mode 100644 (file)
index 0000000..1caeb25
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+EAPI int ECORE_X_EVENT_XDND_ENTER = 0;
+EAPI int ECORE_X_EVENT_XDND_POSITION = 0;
+EAPI int ECORE_X_EVENT_XDND_STATUS = 0;
+EAPI int ECORE_X_EVENT_XDND_LEAVE = 0;
+EAPI int ECORE_X_EVENT_XDND_DROP = 0;
+EAPI int ECORE_X_EVENT_XDND_FINISHED = 0;
+
+static Ecore_X_DND_Source *_source = NULL;
+static Ecore_X_DND_Target *_target = NULL;
+static int _ecore_x_dnd_init_count = 0;
+
+typedef struct _Version_Cache_Item
+{
+   Ecore_X_Window win;
+   int ver;
+} Version_Cache_Item;
+static Version_Cache_Item *_version_cache = NULL;
+static int _version_cache_num = 0, _version_cache_alloc = 0;
+
+void
+_ecore_x_dnd_init(void)
+{
+   if (!_ecore_x_dnd_init_count)
+     {
+       _source = calloc(1, sizeof(Ecore_X_DND_Source));
+       _source->version = ECORE_X_DND_VERSION;
+       _source->win = None;
+       _source->dest = None;
+       _source->state = ECORE_X_DND_SOURCE_IDLE;
+       _source->prev.window = 0;
+
+       _target = calloc(1, sizeof(Ecore_X_DND_Target));
+       _target->win = None;
+       _target->source = None;
+       _target->state = ECORE_X_DND_TARGET_IDLE;
+       
+       ECORE_X_EVENT_XDND_ENTER              = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_POSITION           = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_STATUS             = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_LEAVE              = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_DROP               = ecore_event_type_new();
+       ECORE_X_EVENT_XDND_FINISHED           = ecore_event_type_new();
+     }
+
+   _ecore_x_dnd_init_count++;
+}
+
+void
+_ecore_x_dnd_shutdown(void)
+{
+   _ecore_x_dnd_init_count--;
+   if (_ecore_x_dnd_init_count > 0)
+     return;
+
+   if (_source)
+     free(_source);
+   _source = NULL;
+
+   if (_target)
+     free(_target);
+   _target = NULL;
+
+   _ecore_x_dnd_init_count = 0;
+}
+
+static int
+_ecore_x_dnd_converter_copy(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret)
+{
+   XTextProperty text_prop;
+   char *mystr;
+   XICCEncodingStyle style = XTextStyle;
+
+   if (!data || !size)
+     return 0;
+
+   mystr = calloc(1, size + 1);
+   if (!mystr) return 0;
+   memcpy(mystr, data, size);
+
+   if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
+     {
+       int bufsize = strlen((char *)text_prop.value) + 1;
+       *data_ret = malloc(bufsize);
+       memcpy(*data_ret, text_prop.value, bufsize);
+       *size_ret = bufsize;
+       XFree(text_prop.value);
+       free(mystr);
+       return 1;
+     }
+   else
+     {
+       free(mystr);
+       return 0;
+     }
+}
+
+EAPI void
+ecore_x_dnd_aware_set(Ecore_X_Window win, int on)
+{
+   Ecore_X_Atom prop_data = ECORE_X_DND_VERSION;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (on)
+     ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE,
+                                     XA_ATOM, 32, &prop_data, 1);
+   else
+     ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE);
+}
+
+EAPI int
+ecore_x_dnd_version_get(Ecore_X_Window win)
+{
+   unsigned char *prop_data;
+   int num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   // this looks hacky - and it is, but we need a way of caching info about
+   // a window while dragging, because we literally query this every mouse
+   // move and going to and from x multiple times per move is EXPENSIVE
+   // and slows things down, puts lots of load on x etc.
+   if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
+     {
+       if (_version_cache)
+         {
+            int i;
+            
+            for (i = 0; i < _version_cache_num; i++)
+              {
+                 if (_version_cache[i].win == win)
+                   return _version_cache[i].ver;
+              }
+         }
+     }
+     
+   if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE,
+                                        XA_ATOM, 32, &prop_data, &num))
+     {
+       int version = (int) *prop_data;
+       free(prop_data);
+       if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
+         {
+            _version_cache_num++;
+            if (_version_cache_num > _version_cache_alloc)
+              _version_cache_alloc += 16;
+            _version_cache = realloc(_version_cache, _version_cache_alloc * sizeof(Version_Cache_Item));
+            _version_cache[_version_cache_num - 1].win = win;
+            _version_cache[_version_cache_num - 1].ver = version;
+         }
+       return version;
+     }
+   if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
+     {
+       _version_cache_num++;
+       if (_version_cache_num > _version_cache_alloc)
+         _version_cache_alloc += 16;
+       _version_cache = realloc(_version_cache, _version_cache_alloc * sizeof(Version_Cache_Item));
+       _version_cache[_version_cache_num - 1].win = win;
+       _version_cache[_version_cache_num - 1].ver = 0;
+     }
+   return 0;
+}
+
+EAPI int
+ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type)
+{
+   int                  num, i, ret = 0;
+   unsigned char       *data;
+   Ecore_X_Atom        *atoms, atom;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                        XA_ATOM, 32, &data, &num))
+     return ret;
+
+   atom = ecore_x_atom_get(type);
+   atoms = (Ecore_X_Atom *)data;
+
+   for (i = 0; i < num; ++i)
+     {
+       if (atom == atoms[i])
+         {
+            ret = 1;
+            break;
+         }
+     }
+
+   XFree(data);
+   return ret;
+}
+
+EAPI void
+ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on)
+{
+   Ecore_X_Atom      atom;
+   Ecore_X_Atom      *oldset = NULL, *newset = NULL;
+   int               i, j = 0, num = 0;
+   unsigned char     *data = NULL;
+   unsigned char     *old_data = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atom = ecore_x_atom_get(type);
+   ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                    XA_ATOM, 32, &old_data, &num);
+   oldset = (Ecore_X_Atom *)old_data;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (on)
+     {
+       if (ecore_x_dnd_type_isset(win, type))
+         {
+            XFree(old_data);
+            return;
+         }
+       newset = calloc(num + 1, sizeof(Ecore_X_Atom));
+       if (!newset) return;
+       data = (unsigned char *)newset;
+
+       for (i = 0; i < num; i++)
+         newset[i + 1] = oldset[i];
+       /* prepend the new type */
+       newset[0] = atom;
+
+       ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                        XA_ATOM, 32, data, num + 1);
+     }
+   else
+     {
+       if (!ecore_x_dnd_type_isset(win, type))
+         {
+            XFree(old_data);
+            return;
+         }
+       newset = calloc(num - 1, sizeof(Ecore_X_Atom));
+       if (!newset)
+         {
+            XFree(old_data);
+            return;
+         }
+       data = (unsigned char *)newset;
+       for (i = 0; i < num; i++)
+         if (oldset[i] != atom)
+           newset[j++] = oldset[i];
+
+       ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                        XA_ATOM, 32, data, num - 1);
+     }
+   XFree(oldset);
+   free(newset);
+}
+
+EAPI void
+ecore_x_dnd_types_set(Ecore_X_Window win, const char **types, unsigned int num_types)
+{
+   Ecore_X_Atom      *newset = NULL;
+   unsigned int      i;
+   unsigned char     *data = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!num_types)
+     {
+       ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST);
+     }
+   else
+     {
+       newset = calloc(num_types, sizeof(Ecore_X_Atom));
+       if (!newset) return;
+       data = (unsigned char *)newset;
+       for (i = 0; i < num_types; i++)
+         {
+            newset[i] = ecore_x_atom_get(types[i]);
+            ecore_x_selection_converter_atom_add(newset[i], _ecore_x_dnd_converter_copy);
+         }
+       ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                        XA_ATOM, 32, data, num_types);
+       free(newset);
+     }
+}
+
+EAPI void
+ecore_x_dnd_actions_set(Ecore_X_Window win, Ecore_X_Atom *actions, unsigned int num_actions)
+{
+   unsigned int      i;
+   unsigned char     *data = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!num_actions)
+     {
+       ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_ACTION_LIST);
+     }
+   else
+     {
+       data = (unsigned char *)actions;
+       for (i = 0; i < num_actions; i++)
+         {
+            ecore_x_selection_converter_atom_add(actions[i], _ecore_x_dnd_converter_copy);
+         }
+       ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_ACTION_LIST,
+                                        XA_ATOM, 32, data, num_actions);
+     }
+}
+
+Ecore_X_DND_Source *
+_ecore_x_dnd_source_get(void)
+{
+   return _source;
+}
+
+Ecore_X_DND_Target *
+_ecore_x_dnd_target_get(void)
+{
+   return _target;
+}
+
+EAPI int
+ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
+{
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_dnd_version_get(source))
+     return 0;
+
+   /* Take ownership of XdndSelection */
+   if (!ecore_x_selection_xdnd_set(source, data, size))
+     return 0;
+
+   if (_version_cache)
+     {
+       free(_version_cache);
+       _version_cache = NULL;
+       _version_cache_num = 0;
+       _version_cache_alloc = 0;
+     }
+   ecore_x_window_shadow_tree_flush();
+   
+   _source->win = source;
+   ecore_x_window_ignore_set(_source->win, 1);
+   _source->state = ECORE_X_DND_SOURCE_DRAGGING;
+   _source->time = _ecore_x_event_last_time;
+   _source->prev.window = 0;
+
+   /* Default Accepted Action: move */
+   _source->action = ECORE_X_ATOM_XDND_ACTION_MOVE;
+   _source->accepted_action = None;
+   _source->dest = None;
+
+   return 1;
+}
+
+EAPI int
+ecore_x_dnd_drop(void)
+{
+   XEvent xev;
+   int status = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (_source->dest)
+     {
+       xev.xany.type = ClientMessage;
+       xev.xany.display = _ecore_x_disp;
+       xev.xclient.format = 32;
+       xev.xclient.window = _source->dest;
+
+       if (_source->will_accept)
+         {
+            xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP;
+            xev.xclient.data.l[0] = _source->win;
+            xev.xclient.data.l[1] = 0;
+            xev.xclient.data.l[2] = _source->time;
+            XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev);
+            _source->state = ECORE_X_DND_SOURCE_DROPPED;
+            status = 1;
+         }
+       else
+         {
+            xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
+            xev.xclient.data.l[0] = _source->win;
+            xev.xclient.data.l[1] = 0;
+            XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev);
+            _source->state = ECORE_X_DND_SOURCE_IDLE;
+         }
+     }
+   else
+     {
+       /* Dropping on nothing */
+       ecore_x_selection_xdnd_clear();
+       _source->state = ECORE_X_DND_SOURCE_IDLE;
+     }
+   ecore_x_window_ignore_set(_source->win, 0);
+
+   _source->prev.window = 0;
+
+   return status;
+}
+
+EAPI void
+ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action)
+{
+   XEvent xev;
+
+   if (_target->state == ECORE_X_DND_TARGET_IDLE)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   memset(&xev, 0, sizeof(XEvent));
+
+   _target->will_accept = will_accept;
+
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.message_type = ECORE_X_ATOM_XDND_STATUS;
+   xev.xclient.format = 32;
+   xev.xclient.window = _target->source;
+
+   xev.xclient.data.l[0] = _target->win;
+   xev.xclient.data.l[1] = 0;
+   if (will_accept)
+     xev.xclient.data.l[1] |= 0x1UL;
+   if (!suppress)
+     xev.xclient.data.l[1] |= 0x2UL;
+
+   /* Set rectangle information */
+   xev.xclient.data.l[2] = rectangle.x;
+   xev.xclient.data.l[2] <<= 16;
+   xev.xclient.data.l[2] |= rectangle.y;
+   xev.xclient.data.l[3] = rectangle.width;
+   xev.xclient.data.l[3] <<= 16;
+   xev.xclient.data.l[3] |= rectangle.height;
+
+   if (will_accept)
+     {
+       xev.xclient.data.l[4] = action;
+       _target->accepted_action = action;
+     }
+   else
+     {
+       xev.xclient.data.l[4] = None;
+       _target->accepted_action = action;
+     }
+
+   XSendEvent(_ecore_x_disp, _target->source, False, 0, &xev);
+}
+
+EAPI void
+ecore_x_dnd_send_finished(void)
+{
+   XEvent   xev;
+
+   if (_target->state == ECORE_X_DND_TARGET_IDLE)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xany.type = ClientMessage;
+   xev.xany.display = _ecore_x_disp;
+   xev.xclient.message_type = ECORE_X_ATOM_XDND_FINISHED;
+   xev.xclient.format = 32;
+   xev.xclient.window = _target->source;
+
+   xev.xclient.data.l[0] = _target->win;
+   xev.xclient.data.l[1] = 0;
+   xev.xclient.data.l[2] = 0;
+   if (_target->will_accept)
+     {
+       xev.xclient.data.l[1] |= 0x1UL;
+       xev.xclient.data.l[2] = _target->accepted_action;
+     }
+   XSendEvent(_ecore_x_disp, _target->source, False, 0, &xev);
+
+   _target->state = ECORE_X_DND_TARGET_IDLE;
+}
+
+void
+ecore_x_dnd_source_action_set(Ecore_X_Atom action)
+{
+   _source->action = action;
+   if (_source->prev.window)
+     _ecore_x_dnd_drag(_source->prev.window, _source->prev.x, _source->prev.y);
+}
+
+Ecore_X_Atom
+ecore_x_dnd_source_action_get(void)
+{
+   return _source->action;
+}
+
+void
+_ecore_x_dnd_drag(Ecore_X_Window root, int x, int y)
+{
+   XEvent          xev;
+   Ecore_X_Window  win;
+   Ecore_X_Window *skip;
+   int             num;
+
+   if (_source->state != ECORE_X_DND_SOURCE_DRAGGING)
+     return;
+
+   /* Preinitialize XEvent struct */
+   memset(&xev, 0, sizeof(XEvent));
+   xev.xany.type = ClientMessage;
+   xev.xany.display = _ecore_x_disp;
+   xev.xclient.format = 32;
+
+   /* Attempt to find a DND-capable window under the cursor */
+   skip = ecore_x_window_ignore_list(&num);
+// WARNING - this function is HEAVY. it goes to and from x a LOT walking the
+// window tree - use the SHADOW version - makes a 1-off tree copy, then uses
+// that instead.
+//   win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
+   win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num);
+
+// NOTE: This now uses the shadow version to find parent windows
+//   while ((win) && !(ecore_x_dnd_version_get(win)))
+//     win = ecore_x_window_parent_get(win);
+   while ((win) && !(ecore_x_dnd_version_get(win)))
+     win = ecore_x_window_shadow_parent_get(root, win);
+
+   /* Send XdndLeave to current destination window if we have left it */
+   if ((_source->dest) && (win != _source->dest))
+     {
+       xev.xclient.window = _source->dest;
+       xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE;
+       xev.xclient.data.l[0] = _source->win;
+       xev.xclient.data.l[1] = 0;
+
+       XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev);
+       _source->suppress = 0;
+     }
+
+   if (win)
+     {
+       int x1, x2, y1, y2;
+
+       _source->version = MIN(ECORE_X_DND_VERSION,
+                            ecore_x_dnd_version_get(win));
+       if (win != _source->dest)
+         {
+            int i;
+            unsigned char *data;
+            Ecore_X_Atom *types;
+
+            ecore_x_window_prop_property_get(_source->win, ECORE_X_ATOM_XDND_TYPE_LIST,
+                                             XA_ATOM, 32, &data, &num);
+            types = (Ecore_X_Atom *)data;
+
+            /* Entered new window, send XdndEnter */
+            xev.xclient.window = win;
+            xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER;
+            xev.xclient.data.l[0] = _source->win;
+            xev.xclient.data.l[1] = 0;
+            if (num > 3)
+              xev.xclient.data.l[1] |= 0x1UL;
+            else
+              xev.xclient.data.l[1] &= 0xfffffffeUL;
+            xev.xclient.data.l[1] |= ((unsigned long) _source->version) << 24;
+
+            for (i = 2; i < 5; i++)
+              xev.xclient.data.l[i] = 0;
+            for (i = 0; i < MIN(num, 3); ++i)
+              xev.xclient.data.l[i + 2] = types[i];
+            XFree(data);
+            XSendEvent(_ecore_x_disp, win, False, 0, &xev);
+            _source->await_status = 0;
+            _source->will_accept = 0;
+         }
+
+       /* Determine if we're still in the rectangle from the last status */
+       x1 = _source->rectangle.x;
+       x2 = _source->rectangle.x + _source->rectangle.width;
+       y1 = _source->rectangle.y;
+       y2 = _source->rectangle.y + _source->rectangle.height;
+
+       if ((!_source->await_status) ||
+           (!_source->suppress) ||
+           ((x < x1) || (x > x2) || (y < y1) || (y > y2)))
+         {
+            xev.xclient.window = win;
+            xev.xclient.message_type = ECORE_X_ATOM_XDND_POSITION;
+            xev.xclient.data.l[0] = _source->win;
+            xev.xclient.data.l[1] = 0; /* Reserved */
+            xev.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff);
+            xev.xclient.data.l[3] = _source->time; /* Version 1 */
+            xev.xclient.data.l[4] = _source->action; /* Version 2, Needs to be pre-set */
+            XSendEvent(_ecore_x_disp, win, False, 0, &xev);
+
+            _source->await_status = 1; 
+         }
+     }
+
+   _source->prev.x = x;
+   _source->prev.y = y;
+   _source->prev.window = root;
+   _source->dest = win;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_dpms.c b/src/lib/ecore_x/xlib/ecore_x_dpms.c
new file mode 100644 (file)
index 0000000..3b15dbc
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+
+static int _dpms_available;
+
+void
+_ecore_x_dpms_init(void)
+{
+#ifdef ECORE_XDPMS
+   int _dpms_major, _dpms_minor;
+
+   _dpms_major = 1;
+   _dpms_minor = 0;
+
+   if (DPMSGetVersion(_ecore_x_disp, &_dpms_major, &_dpms_minor))
+     _dpms_available = 1;
+   else
+     _dpms_available = 0;
+#else
+   _dpms_available = 0;
+#endif
+}
+
+/**
+ * @defgroup Ecore_X_DPMS_Group X DPMS Extension Functions
+ *
+ * Functions related to the X DPMS extension.
+ */
+
+/**
+ * Checks if the X DPMS extension is available on the server.
+ * @return @c 1 if the X DPMS extension is available, @c 0 otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_query(void)
+{
+   return _dpms_available;
+}
+
+/**
+ * Checks if the X server is capable of DPMS.
+ * @return @c 1 if the X server is capable of DPMS, @c 0 otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_capable_get(void)
+{
+#ifdef ECORE_XDPMS
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return DPMSCapable(_ecore_x_disp);
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Checks the DPMS state of the display.
+ * @return @c 1 if DPMS is enabled, @c 0 otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_enabled_get(void)
+{
+#ifdef ECORE_XDPMS
+   unsigned char state;
+   unsigned short power_lvl;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSInfo(_ecore_x_disp, &power_lvl, &state);
+   return state;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Sets the DPMS state of the display.
+ * @param enabled @c 0 to disable DPMS characteristics of the server, enable it otherwise.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_enabled_set(int enabled)
+{
+#ifdef ECORE_XDPMS
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (enabled)
+     DPMSEnable(_ecore_x_disp);
+   else
+     DPMSDisable(_ecore_x_disp);
+#endif
+}
+
+/**
+ * Gets the timeouts. The values are in unit of seconds.
+ * @param standby Amount of time of inactivity before standby mode will be invoked.
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeouts_get(unsigned int *standby, unsigned int *suspend, unsigned int *off)
+{
+#ifdef ECORE_XDPMS
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, (unsigned short *)standby, 
+                  (unsigned short *)suspend, (unsigned short *)off);
+#endif
+}
+
+/**
+ * Sets the timeouts. The values are in unit of seconds.
+ * @param standby Amount of time of inactivity before standby mode will be invoked.
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI int
+ecore_x_dpms_timeouts_set(unsigned int standby, unsigned int suspend, unsigned int off)
+{
+#ifdef ECORE_XDPMS
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return DPMSSetTimeouts(_ecore_x_disp, standby, suspend, off);
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Returns the amount of time of inactivity before standby mode is invoked.
+ * @return The standby timeout value.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_standby_get()
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   return standby;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Returns the amount of time of inactivity before the second level of
+ * power saving is invoked.
+ * @return The suspend timeout value.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_suspend_get()
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   return suspend;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Returns the amount of time of inactivity before the third and final
+ * level of power saving is invoked.
+ * @return The off timeout value.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI unsigned int
+ecore_x_dpms_timeout_off_get()
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   return off;
+#else
+   return 0;
+#endif
+}
+
+/**
+ * Sets the standby timeout (in unit of seconds).
+ * @param new_standby Amount of time of inactivity before standby mode will be invoked.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_standby_set(unsigned int new_timeout)
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   DPMSSetTimeouts(_ecore_x_disp, new_timeout, suspend, off);
+#endif
+}
+
+/**
+ * Sets the suspend timeout (in unit of seconds).
+ * @param suspend Amount of time of inactivity before the screen is placed into suspend mode.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout)
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   DPMSSetTimeouts(_ecore_x_disp, standby, new_timeout, off);
+#endif
+}
+
+/**
+ * Sets the off timeout (in unit of seconds).
+ * @param off     Amount of time of inactivity before the monitor is shut off.
+ * @ingroup Ecore_X_DPMS_Group
+ */
+EAPI void
+ecore_x_dpms_timeout_off_set(unsigned int new_timeout)
+{
+#ifdef ECORE_XDPMS
+   unsigned short standby, suspend, off;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off);
+   DPMSSetTimeouts(_ecore_x_disp, standby, suspend, new_timeout);
+#endif
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_drawable.c b/src/lib/ecore_x/xlib/ecore_x_drawable.c
new file mode 100644 (file)
index 0000000..91d7959
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+
+
+/**
+ * @defgroup Ecore_X_Drawable_Group X Drawable Functions
+ *
+ * Functions that operate on drawables.
+ */
+
+
+/**
+ * Retrieves the geometry of the given drawable.
+ * @param d The given drawable.
+ * @param x Pointer to an integer into which the X position is to be stored.
+ * @param y Pointer to an integer into which the Y position is to be stored.
+ * @param w Pointer to an integer into which the width is to be stored.
+ * @param h Pointer to an integer into which the height is to be stored.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI void
+ecore_x_drawable_geometry_get(Ecore_X_Drawable d, int *x, int *y, int *w, int *h)
+{
+   Window         dummy_win;
+   int            ret_x, ret_y;
+   unsigned int   ret_w, ret_h, dummy_border, dummy_depth;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &ret_x, &ret_y,
+                     &ret_w, &ret_h, &dummy_border, &dummy_depth))
+   {
+      ret_x = 0;
+      ret_y = 0;
+      ret_w = 0;
+      ret_h = 0;
+   }
+
+   if (x) *x = ret_x;
+   if (y) *y = ret_y;
+   if (w) *w = (int) ret_w;
+   if (h) *h = (int) ret_h;
+}
+
+/**
+ * Retrieves the width of the border of the given drawable.
+ * @param  d The given drawable.
+ * @return The border width of the given drawable.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI int
+ecore_x_drawable_border_width_get(Ecore_X_Drawable d)
+{
+   Window         dummy_win;
+   int            dummy_x, dummy_y;
+   unsigned int   dummy_w, dummy_h, border_ret, dummy_depth;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &dummy_x, &dummy_y,
+                     &dummy_w, &dummy_h, &border_ret, &dummy_depth))
+      border_ret = 0;
+
+   return (int) border_ret;
+}
+
+/**
+ * Retrieves the depth of the given drawable.
+ * @param  d The given drawable.
+ * @return The depth of the given drawable.
+ * @ingroup Ecore_X_Drawable_Group
+ */
+EAPI int
+ecore_x_drawable_depth_get(Ecore_X_Drawable d)
+{
+   Window         dummy_win;
+   int            dummy_x, dummy_y;
+   unsigned int   dummy_w, dummy_h, dummy_border, depth_ret;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &dummy_x, &dummy_y,
+                     &dummy_w, &dummy_h, &dummy_border, &depth_ret))
+      depth_ret = 0;
+
+   return (int) depth_ret;
+}
+
+/**
+ * Fill the specified rectangle on a drawable.
+ * @param d The given drawable.
+ * @param gc The graphic context that controls the fill rules.
+ * @param x The X coordinate of the top-left corner of the rectangle.
+ * @param y The Y coordinate of the top-left corner of the rectangle.
+ * @param width The width of the rectangle.
+ * @param height The height of the rectangle.
+ */
+EAPI void
+ecore_x_drawable_rectangle_fill(Ecore_X_Drawable d, Ecore_X_GC gc, int x, int y, int width, int height)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFillRectangle(_ecore_x_disp, d, gc, x, y, width, height);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_e.c b/src/lib/ecore_x/xlib/ecore_x_e.c
new file mode 100644 (file)
index 0000000..5493ca4
--- /dev/null
@@ -0,0 +1,860 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * OLD E hints
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+EAPI void
+ecore_x_e_init(void)
+{
+}
+
+EAPI void
+ecore_x_e_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb)
+{
+   unsigned int frames[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   frames[0] = fl;
+   frames[1] = fr;
+   frames[2] = ft;
+   frames[3] = fb;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_FRAME_SIZE, frames, 4);
+}
+
+EAPI void
+ecore_x_e_virtual_keyboard_set(Ecore_X_Window win, unsigned int is_keyboard)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD,
+                                 &is_keyboard, 1);
+}
+
+EAPI int
+ecore_x_e_virtual_keyboard_get(Ecore_X_Window win)
+{
+   unsigned int val;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD, &val, 1))
+     return 0;
+   return val;
+}
+
+static Ecore_X_Virtual_Keyboard_State
+_ecore_x_e_vkbd_state_get(Ecore_X_Atom atom)
+{
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_ON;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_IP;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_URL;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD;
+   if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME) 
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME;
+   return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN;
+}
+
+static Ecore_X_Atom
+_ecore_x_e_vkbd_atom_get(Ecore_X_Virtual_Keyboard_State state)
+{
+   switch (state)
+     {
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_ON: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_IP: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_URL: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD;
+      case ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME: 
+        return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME;
+      default: return 0;
+     }
+   return 0;
+}
+
+EAPI void
+ecore_x_e_virtual_keyboard_state_set(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state)
+{
+   Ecore_X_Atom atom = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atom = _ecore_x_e_vkbd_atom_get(state);
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE,
+                               &atom, 1);
+}
+
+EAPI Ecore_X_Virtual_Keyboard_State
+ecore_x_e_virtual_keyboard_state_get(Ecore_X_Window win)
+{
+   Ecore_X_Atom atom;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE,
+                                    &atom, 1))
+     return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN;
+   return _ecore_x_e_vkbd_state_get(atom);
+}
+
+EAPI void
+ecore_x_e_virtual_keyboard_state_send(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                _ecore_x_e_vkbd_atom_get(state),
+                                0, 0, 0, 0);
+}
+
+static Ecore_X_Atom 
+_ecore_x_e_illume_atom_get(Ecore_X_Illume_Mode mode) 
+{
+   switch (mode) 
+     {
+      case ECORE_X_ILLUME_MODE_SINGLE:
+        return ECORE_X_ATOM_E_ILLUME_MODE_SINGLE;
+      case ECORE_X_ILLUME_MODE_DUAL_TOP:
+        return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP;
+      case ECORE_X_ILLUME_MODE_DUAL_LEFT:
+        return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT;
+      default:
+        return ECORE_X_ILLUME_MODE_UNKNOWN;;
+     }
+   return ECORE_X_ILLUME_MODE_UNKNOWN;
+}
+
+static Ecore_X_Illume_Mode 
+_ecore_x_e_illume_mode_get(Ecore_X_Atom atom) 
+{
+   if (atom == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE)
+     return ECORE_X_ILLUME_MODE_SINGLE;
+   if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP)
+     return ECORE_X_ILLUME_MODE_DUAL_TOP;
+   if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT)
+     return ECORE_X_ILLUME_MODE_DUAL_LEFT;
+   return ECORE_X_ILLUME_MODE_UNKNOWN;
+}
+
+EAPI void 
+ecore_x_e_illume_zone_set(Ecore_X_Window win, Ecore_X_Window zone) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE, 
+                                  &zone, 1);
+}
+
+EAPI Ecore_X_Window 
+ecore_x_e_illume_zone_get(Ecore_X_Window win) 
+{
+   Ecore_X_Window zone;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_window_get(win, ECORE_X_ATOM_E_ILLUME_ZONE, 
+                                       &zone, 1)) return 0;
+   return zone;
+}
+
+EAPI void 
+ecore_x_e_illume_zone_list_set(Ecore_X_Window win, Ecore_X_Window *zones, unsigned int n_zones) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, 
+                                  zones, n_zones);
+}
+
+EAPI void 
+ecore_x_e_illume_conformant_set(Ecore_X_Window win, unsigned int is_conformant) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT,
+                                 &is_conformant, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_conformant_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_mode_set(Ecore_X_Window win, Ecore_X_Illume_Mode mode) 
+{
+   Ecore_X_Atom atom = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atom = _ecore_x_e_illume_atom_get(mode);
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_MODE,
+                                 &atom, 1);
+}
+
+EAPI Ecore_X_Illume_Mode 
+ecore_x_e_illume_mode_get(Ecore_X_Window win) 
+{
+   Ecore_X_Atom atom = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_ILLUME_MODE, &atom, 1))
+     return ECORE_X_ILLUME_MODE_UNKNOWN;
+   return _ecore_x_e_illume_mode_get(atom);
+}
+
+EAPI void 
+ecore_x_e_illume_mode_send(Ecore_X_Window win, Ecore_X_Illume_Mode mode) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_MODE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                _ecore_x_e_illume_atom_get(mode),
+                                0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_focus_back_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_BACK,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_focus_forward_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_focus_home_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_HOME,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_close_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_CLOSE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, 
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_home_new_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_NEW,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, 
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_home_del_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_DEL,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, 
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_drag_set(Ecore_X_Window win, unsigned int drag) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG, &drag, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_drag_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG, &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_drag_locked_set(Ecore_X_Window win, unsigned int is_locked) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, 
+                                  &is_locked, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_drag_locked_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_drag_start_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_START,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_drag_end_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_END,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_indicator_geometry_set(Ecore_X_Window win, int x, int y, int w, int h) 
+{
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   geom[0] = x;
+   geom[1] = y;
+   geom[2] = w;
+   geom[3] = h;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, 
+                                  geom, 4);
+}
+
+EAPI int 
+ecore_x_e_illume_indicator_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h) 
+{
+   int ret = 0;
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = 
+     ecore_x_window_prop_card32_get(win, 
+                                    ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, 
+                                    geom, 4);
+   if (ret != 4) return 0;
+   if (x) *x = geom[0];
+   if (y) *y = geom[1];
+   if (w) *w = geom[2];
+   if (h) *h = geom[3];
+   return 1;
+}
+
+EAPI void 
+ecore_x_e_illume_softkey_geometry_set(Ecore_X_Window win, int x, int y, int w, int h) 
+{
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   geom[0] = x;
+   geom[1] = y;
+   geom[2] = w;
+   geom[3] = h;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, 
+                                  geom, 4);
+}
+
+EAPI int 
+ecore_x_e_illume_softkey_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h) 
+{
+   int ret = 0;
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = 
+     ecore_x_window_prop_card32_get(win, 
+                                    ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, 
+                                    geom, 4);
+   if (ret != 4) return 0;
+   if (x) *x = geom[0];
+   if (y) *y = geom[1];
+   if (w) *w = geom[2];
+   if (h) *h = geom[3];
+   return 1;
+}
+
+EAPI void 
+ecore_x_e_illume_keyboard_geometry_set(Ecore_X_Window win, int x, int y, int w, int h) 
+{
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   geom[0] = x;
+   geom[1] = y;
+   geom[2] = w;
+   geom[3] = h;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, 
+                                  geom, 4);
+}
+
+EAPI int 
+ecore_x_e_illume_keyboard_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h) 
+{
+   int ret = 0;
+   unsigned int geom[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = 
+     ecore_x_window_prop_card32_get(win, 
+                                    ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, 
+                                    geom, 4);
+   if (ret != 4) return 0;
+   if (x) *x = geom[0];
+   if (y) *y = geom[1];
+   if (w) *w = geom[2];
+   if (h) *h = geom[3];
+   return 1;
+}
+
+static Ecore_X_Atom
+_ecore_x_e_quickpanel_atom_get(Ecore_X_Illume_Quickpanel_State state)
+{
+   switch (state) 
+     {
+      case ECORE_X_ILLUME_QUICKPANEL_STATE_ON:
+        return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON;
+      case ECORE_X_ILLUME_QUICKPANEL_STATE_OFF:
+        return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF;
+      default:
+        return 0;
+     }
+   return 0;
+}
+
+static Ecore_X_Illume_Quickpanel_State
+_ecore_x_e_quickpanel_state_get(Ecore_X_Atom atom)
+{
+   if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON) 
+     return ECORE_X_ILLUME_QUICKPANEL_STATE_ON;
+   if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF)
+     return ECORE_X_ILLUME_QUICKPANEL_STATE_OFF;
+   return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN;
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_set(Ecore_X_Window win, unsigned int is_quickpanel) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL,
+                                 &is_quickpanel, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_quickpanel_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_state_set(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state) 
+{
+   Ecore_X_Atom atom = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atom = _ecore_x_e_quickpanel_atom_get(state);
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE,
+                               &atom, 1);
+}
+
+EAPI Ecore_X_Illume_Quickpanel_State 
+ecore_x_e_illume_quickpanel_state_get(Ecore_X_Window win) 
+{
+   Ecore_X_Atom atom;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE,
+                                    &atom, 1))
+     return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN;
+   return _ecore_x_e_quickpanel_state_get(atom);
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_state_send(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                _ecore_x_e_quickpanel_atom_get(state),
+                                0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_state_toggle(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, 
+                                 ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                0, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_priority_major_set(Ecore_X_Window win, unsigned int priority) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, 
+                                  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, 
+                                  &priority, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_quickpanel_priority_major_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_priority_minor_set(Ecore_X_Window win, unsigned int priority) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, 
+                                  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, 
+                                  &priority, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_quickpanel_priority_minor_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_zone_set(Ecore_X_Window win, unsigned int zone) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, 
+                                  ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, 
+                                  &zone, 1);
+}
+
+EAPI int 
+ecore_x_e_illume_quickpanel_zone_get(Ecore_X_Window win) 
+{
+   unsigned int val = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, 
+                                       &val, 1))
+     return 0;
+   return val;
+}
+
+EAPI void 
+ecore_x_e_illume_quickpanel_position_update_send(Ecore_X_Window win) 
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, 
+                                 ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE,
+                                ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
+                                1, 0, 0, 0, 0);
+}
+
+EAPI void 
+ecore_x_e_comp_sync_counter_set(Ecore_X_Window win, Ecore_X_Sync_Counter counter)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (counter)
+     ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER,
+                                  ECORE_X_ATOM_CARDINAL, &counter, 1);
+   else
+     ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER);
+}
+
+EAPI Ecore_X_Sync_Counter
+ecore_x_e_comp_sync_counter_get(Ecore_X_Window win)
+{
+   int ret = 0;
+   Ecore_X_Sync_Counter counter = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = 
+     ecore_x_window_prop_xid_get(win, 
+                                 ECORE_X_ATOM_E_COMP_SYNC_COUNTER,
+                                 ECORE_X_ATOM_CARDINAL,
+                                 &counter, 1);
+   if (ret != 1) return 0;
+   return counter;
+}
+
+EAPI void
+ecore_x_e_comp_sync_draw_done_send(Ecore_X_Window root, Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, root, False,
+              SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
+
+EAPI void
+ecore_x_e_comp_sync_supported_set(Ecore_X_Window root, Eina_Bool enabled)
+{
+   Ecore_X_Window win;
+
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (enabled)
+     {
+        win = ecore_x_window_new(root, 1, 2, 3, 4);
+        ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED,
+                                     ECORE_X_ATOM_WINDOW, &win, 1);
+        ecore_x_window_prop_xid_set(root, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED,
+                                     ECORE_X_ATOM_WINDOW, &win, 1);
+     }
+   else
+     {
+        int ret;
+        
+        ret = 
+          ecore_x_window_prop_xid_get(root, 
+                                      ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED,
+                                      ECORE_X_ATOM_WINDOW,
+                                      &win, 1);
+        if ((ret == 1) && (win))
+          {
+             ecore_x_window_prop_property_del(root, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED);
+             ecore_x_window_free(win);
+          }
+     }
+}
+
+EAPI Eina_Bool
+ecore_x_e_comp_sync_supported_get(Ecore_X_Window root)
+{
+   Ecore_X_Window win, win2;
+   int ret;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+   ret = 
+     ecore_x_window_prop_xid_get(root, 
+                                 ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED,
+                                 ECORE_X_ATOM_WINDOW,
+                                 &win, 1);
+   if ((ret == 1) && (win))
+     {
+        ret = 
+          ecore_x_window_prop_xid_get(win, 
+                                      ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED,
+                                      ECORE_X_ATOM_WINDOW,
+                                      &win2, 1);
+        if ((ret == 1) && (win2 == win))
+          {
+             return 1;
+          }
+     }
+   return 0;
+}
+
+EAPI void
+ecore_x_e_comp_sync_begin_send(Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_BEGIN;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, win, False,
+              NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
+
+EAPI void
+ecore_x_e_comp_sync_end_send(Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_END;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, win, False,
+              NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
+
+EAPI void
+ecore_x_e_comp_sync_cancel_send(Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_CANCEL;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, win, False,
+              NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
+
+EAPI void
+ecore_x_e_comp_flush_send(Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_FLUSH;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, win, False,
+              NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
+
+EAPI void
+ecore_x_e_comp_dump_send(Ecore_X_Window win)
+{
+   XEvent xev;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_E_COMP_DUMP;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = win;
+   xev.xclient.data.l[1] = 0; // later
+   xev.xclient.data.l[2] = 0; // later
+   xev.xclient.data.l[3] = 0; // later
+   xev.xclient.data.l[4] = 0; // later
+   
+   XSendEvent(_ecore_x_disp, win, False,
+              NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, 
+              &xev);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_error.c b/src/lib/ecore_x/xlib/ecore_x_error.c
new file mode 100644 (file)
index 0000000..ccf3822
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+static void _ecore_x_error_handle(Display * d, XErrorEvent * ev);
+static int  _ecore_x_io_error_handle(Display *d);
+
+static void (*_error_func) (void *data) = NULL;
+static void *_error_data = NULL;
+static void (*_io_error_func) (void *data) = NULL;
+static void *_io_error_data = NULL;
+static int   _error_request_code = 0;
+static int   _error_code = 0;
+
+/**
+ * Set the error handler.
+ * @param func The error handler function
+ * @param data The data to be passed to the handler function
+ * 
+ * Set the X error handler function
+ */
+EAPI void
+ecore_x_error_handler_set(void (*func) (void *data), const void *data)
+{
+   _error_func = func;
+   _error_data = (void *)data;
+}
+
+/**
+ * Set the I/O error handler.
+ * @param func The I/O error handler function
+ * @param data The data to be passed to the handler function
+ * 
+ * Set the X I/O error handler function
+ */
+EAPI void
+ecore_x_io_error_handler_set(void (*func) (void *data), const void *data)
+{
+   _io_error_func = func;
+   _io_error_data = (void *)data;
+}
+
+/**
+ * Get the request code that caused the error.
+ * @return The request code causing the X error
+ * 
+ * Return the X request code that caused the last X error
+ */
+EAPI int
+ecore_x_error_request_get(void)
+{
+   return _error_request_code;
+}
+
+/**
+ * Get the error code from the error.
+ * @return The error code from the X error
+ * 
+ * Return the error code from the last X error
+ */
+EAPI int
+ecore_x_error_code_get(void)
+{
+   return _error_code;
+}
+
+void
+_ecore_x_error_handler_init(void)
+{
+   XSetErrorHandler((XErrorHandler)_ecore_x_error_handle);
+   XSetIOErrorHandler((XIOErrorHandler)_ecore_x_io_error_handle);   
+}
+
+static void
+_ecore_x_error_handle(Display *d, XErrorEvent *ev)
+{
+    if (d == _ecore_x_disp)
+     {
+       _error_request_code = ev->request_code;
+       _error_code = ev->error_code;
+       if (_error_func) _error_func(_error_data);
+     }
+}
+
+static int
+_ecore_x_io_error_handle(Display *d)
+{
+    if (d == _ecore_x_disp)
+     {
+       if (_io_error_func) _io_error_func(_io_error_data);
+       else exit(-1);
+     }
+   return 0;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_events.c b/src/lib/ecore_x/xlib/ecore_x_events.c
new file mode 100644 (file)
index 0000000..a30f610
--- /dev/null
@@ -0,0 +1,2137 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <langinfo.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+/** OpenBSD does not define CODESET
+ * FIXME ??
+ */
+
+#ifndef CODESET
+#define CODESET "INVALID"
+#endif
+
+#if 0
+static void _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_title_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev);
+static void _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev);
+#endif
+
+static Window _ecore_x_mouse_down_last_win = 0;
+static Window _ecore_x_mouse_down_last_last_win = 0;
+static Window _ecore_x_mouse_down_last_event_win = 0;
+static Window _ecore_x_mouse_down_last_last_event_win = 0;
+static Time _ecore_x_mouse_down_last_time = 0;
+static Time _ecore_x_mouse_down_last_last_time = 0;
+static int _ecore_x_mouse_up_count = 0;
+static int _ecore_x_mouse_down_did_triple = 0;
+static int _ecore_x_last_event_mouse_move = 0;
+static Ecore_Event *_ecore_x_last_event_mouse_move_event = NULL;
+
+static void
+_ecore_x_event_free_mouse_move(void *data __UNUSED__, void *ev)
+{
+   Ecore_Event_Mouse_Move *e;
+
+   e = ev;
+   if (_ecore_x_last_event_mouse_move)
+     {
+       _ecore_x_last_event_mouse_move_event = NULL;
+       _ecore_x_last_event_mouse_move = 0;
+     }
+   free(e);
+}
+
+EAPI void
+ecore_x_event_mask_set(Ecore_X_Window w, Ecore_X_Event_Mask mask)
+{
+   XWindowAttributes attr;
+   XSetWindowAttributes s_attr;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!w) w = DefaultRootWindow(_ecore_x_disp);
+   memset(&attr, 0, sizeof(XWindowAttributes));
+   XGetWindowAttributes(_ecore_x_disp, w, &attr);
+   s_attr.event_mask = mask | attr.your_event_mask;
+   XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr);
+}
+
+EAPI void
+ecore_x_event_mask_unset(Ecore_X_Window w, Ecore_X_Event_Mask mask)
+{
+   XWindowAttributes attr;
+   XSetWindowAttributes s_attr;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!w) w = DefaultRootWindow(_ecore_x_disp);
+   memset(&attr, 0, sizeof(XWindowAttributes));
+   XGetWindowAttributes(_ecore_x_disp, w, &attr);
+   s_attr.event_mask = attr.your_event_mask & ~mask;
+   XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr);
+}
+
+#if 0
+static void
+_ecore_x_event_free_window_prop_name_class_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Name_Class_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   if (e->clas) free(e->clas);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_title_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Title_Change *e;
+
+   e = ev;
+   if (e->title) free(e->title);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
+
+   e = ev;
+   if (e->title) free(e->title);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev)
+{
+   Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
+
+   e = ev;
+   if (e->name) free(e->name);
+   free(e);
+}
+#endif
+
+static void
+_ecore_x_event_free_xdnd_enter(void *data __UNUSED__, void *ev)
+{
+   Ecore_X_Event_Xdnd_Enter *e;
+   int i;
+
+   e = ev;
+   for (i = 0; i < e->num_types; i++)
+     XFree(e->types[i]);
+   free(e->types);
+   free(e);
+}
+
+static void
+_ecore_x_event_free_selection_notify(void *data __UNUSED__, void *ev)
+{
+   Ecore_X_Event_Selection_Notify *e;
+   Ecore_X_Selection_Data *sel;
+
+   e = ev;
+   sel = e->data;
+   if (sel->free) sel->free(sel);
+   free(e->target);
+   free(e);
+}
+
+static unsigned int
+_ecore_x_event_modifiers(unsigned int state)
+{
+   unsigned int        modifiers = 0;
+
+   if (state & ECORE_X_MODIFIER_SHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+   if (state & ECORE_X_MODIFIER_CTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+   if (state & ECORE_X_MODIFIER_ALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
+   if (state & ECORE_X_MODIFIER_WIN) modifiers |= ECORE_EVENT_MODIFIER_WIN;
+   if (state & ECORE_X_LOCK_SCROLL) modifiers |= ECORE_EVENT_LOCK_SCROLL;
+   if (state & ECORE_X_LOCK_NUM) modifiers |= ECORE_EVENT_LOCK_NUM;
+   if (state & ECORE_X_LOCK_CAPS) modifiers |= ECORE_EVENT_LOCK_CAPS;
+
+   return modifiers;
+}
+
+void
+_ecore_mouse_move(unsigned int timestamp, unsigned int xmodifiers,
+                 int x, int y,
+                 int x_root, int y_root,
+                 unsigned int event_window,
+                 unsigned int window,
+                 unsigned int root_win,
+                 int same_screen,
+                  int dev, double radx, double rady, double pressure, double angle, double mx, double my, double mrx, double mry)
+{
+   Ecore_Event_Mouse_Move *e;
+   Ecore_Event *event;
+
+   e = malloc(sizeof(Ecore_Event_Mouse_Move));
+   if (!e) return ;
+
+   e->window = window;
+   e->root_window = root_win;
+   e->timestamp = timestamp;
+   e->same_screen = same_screen;
+   e->event_window = event_window;
+
+   e->modifiers = _ecore_x_event_modifiers(xmodifiers);
+   e->x = x;
+   e->y = y;
+   e->root.x = x_root;
+   e->root.y = y_root;
+
+   e->multi.device = dev;
+   e->multi.radius = (radx + rady) / 2;
+   e->multi.radius_x = radx;
+   e->multi.radius_y = rady;
+   e->multi.pressure = pressure;
+   e->multi.angle = angle;
+   e->multi.x = mx;
+   e->multi.y = my;
+   e->multi.root.x = mrx;
+   e->multi.root.y = mry;
+   
+   event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _ecore_x_event_free_mouse_move, NULL);
+
+   _ecore_x_event_last_time = timestamp;
+   _ecore_x_event_last_win = window;
+   _ecore_x_event_last_root_x = x_root;
+   _ecore_x_event_last_root_y = y_root;
+
+   _ecore_x_last_event_mouse_move_event = event;
+}
+
+static void
+_ecore_key_press(int event, XKeyEvent *xevent)
+{
+   Ecore_Event_Key *e;
+   char *compose = NULL;
+   char *tmp = NULL;
+   char *keyname;
+   char *key;
+   char keyname_buffer[256];
+   char compose_buffer[256];
+   KeySym sym;
+   XComposeStatus status;
+   int val;
+
+   _ecore_x_last_event_mouse_move = 0;
+   keyname = XKeysymToString(XKeycodeToKeysym(xevent->display,
+                                             xevent->keycode, 0));
+   if (!keyname)
+     {
+       snprintf(keyname_buffer, sizeof(keyname_buffer), "Keycode-%i", xevent->keycode);
+       keyname = keyname_buffer;
+       if (!keyname) return ;
+     }
+
+   sym = 0;
+   key = NULL;
+   compose = NULL;
+   if (_ecore_x_ic)
+     {
+       Status mbstatus;
+#ifdef X_HAVE_UTF8_STRING
+       val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
+#else
+       val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
+#endif
+       if (mbstatus == XBufferOverflow)
+         {
+            tmp = malloc(sizeof (char) * (val + 1));
+            if (!tmp) return ;
+
+            compose = tmp;
+
+#ifdef X_HAVE_UTF8_STRING
+            val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
+#else
+            val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
+#endif
+            if (val > 0)
+              {
+                 tmp[val] = 0;
+
+#ifndef X_HAVE_UTF8_STRING
+                 compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", tmp);
+                 free(tmp);
+                 tmp = compose;
+#endif
+              }
+            else compose = NULL;
+         }
+       else
+         if (val > 0)
+           {
+              compose_buffer[val] = 0;
+#ifdef X_HAVE_UTF8_STRING
+              compose = compose_buffer;
+#else
+              compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
+              tmp = compose;
+#endif
+           }
+     }
+   else
+     {
+       val = XLookupString(xevent, compose_buffer, sizeof(compose_buffer), &sym, &status);
+       if (val > 0)
+         {
+            compose_buffer[val] = 0;
+            compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
+            tmp = compose;
+         }
+     }
+
+   key = XKeysymToString(sym);
+   if (!key) key = keyname;
+   if (!key) goto on_error;
+
+   e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + (compose ? strlen(compose) : 0) + 3);
+   if (!e) goto on_error;
+
+   e->keyname = (char*) (e + 1);
+   e->key = e->keyname + strlen(keyname) + 1;
+   e->compose = (compose) ? e->key + strlen(key) + 1 : NULL;
+   e->string = e->compose;
+
+   strcpy((char *) e->keyname, keyname);
+   strcpy((char *) e->key, key);
+   if (compose) strcpy((char *) e->compose, compose);
+
+   e->modifiers = _ecore_x_event_modifiers(xevent->state);
+
+   e->timestamp = xevent->time;
+   e->window = xevent->subwindow ? xevent->subwindow : xevent->window;
+   e->event_window = xevent->window;
+   e->same_screen = xevent->same_screen;
+   e->root_window = xevent->root;
+
+   ecore_event_add(event, e, NULL, NULL);
+
+   _ecore_x_event_last_time = e->timestamp;
+
+ on_error:
+   if (tmp) free(tmp);
+}
+
+Ecore_Event_Mouse_Button *
+_ecore_mouse_button(int event,
+                   unsigned int timestamp, unsigned int xmodifiers,
+                   unsigned int buttons,
+                   int x, int y,
+                   int x_root, int y_root,
+                   unsigned int event_window,
+                   unsigned int window,
+                   unsigned int root_win,
+                   int same_screen,
+                    int dev, double radx, double rady, double pressure, double angle, double mx, double my, double mrx, double mry)
+{
+   Ecore_Event_Mouse_Button *e;
+
+   e = malloc(sizeof(Ecore_Event_Mouse_Button));
+   if (!e) return NULL;
+
+   e->window = window;
+   e->root_window = root_win;
+   e->timestamp = timestamp;
+   e->same_screen = same_screen;
+   e->event_window = event_window;
+
+   e->buttons = buttons;
+   e->modifiers = _ecore_x_event_modifiers(xmodifiers);
+   e->double_click = 0;
+   e->triple_click = 0;
+   e->x = x;
+   e->y = y;
+   e->root.x = x_root;
+   e->root.y = y_root;
+
+   if (event_window == window)
+     {
+       if (((int)(timestamp - _ecore_x_mouse_down_last_time) <=
+            (int)(1000 * _ecore_x_double_click_time)) &&
+           (window == _ecore_x_mouse_down_last_win) &&
+           (event_window == _ecore_x_mouse_down_last_event_win)
+           )
+         e->double_click = 1;
+       if (((int)(timestamp - _ecore_x_mouse_down_last_last_time) <=
+            (int)(2 * 1000 * _ecore_x_double_click_time)) &&
+           (window == _ecore_x_mouse_down_last_win) &&
+           (window == _ecore_x_mouse_down_last_last_win) &&
+           (event_window == _ecore_x_mouse_down_last_event_win) &&
+           (event_window == _ecore_x_mouse_down_last_last_event_win)
+           )
+         {
+            e->triple_click = 1;
+            _ecore_x_mouse_down_did_triple = 1;
+         }
+       else
+         _ecore_x_mouse_down_did_triple = 0;
+     }
+
+   if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN
+       && !e->double_click
+       && !e->triple_click)
+     _ecore_x_mouse_up_count = 0;
+   
+   e->multi.device = dev;
+   e->multi.radius = (radx + rady) / 2;
+   e->multi.radius_x = radx;
+   e->multi.radius_y = rady;
+   e->multi.pressure = pressure;
+   e->multi.angle = angle;
+   e->multi.x = mx;
+   e->multi.y = my;
+   e->multi.root.x = mrx;
+   e->multi.root.y = mry;
+   
+   _ecore_x_event_last_time = e->timestamp;
+   _ecore_x_event_last_win = e->window;
+   _ecore_x_event_last_root_x = x_root;
+   _ecore_x_event_last_root_y = y_root;
+
+   ecore_event_add(event, e, NULL, NULL);
+
+   return e;
+}
+
+void
+_ecore_x_event_handle_any_event(XEvent *xevent)
+{
+   XEvent* ev = malloc(sizeof(XEvent));
+   
+   memcpy(ev, xevent, sizeof(XEvent));
+   ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_key_press(XEvent *xevent)
+{
+   _ecore_key_press(ECORE_EVENT_KEY_DOWN, (XKeyEvent *) xevent);
+}
+
+void
+_ecore_x_event_handle_key_release(XEvent *xevent)
+{
+   _ecore_key_press(ECORE_EVENT_KEY_UP, (XKeyEvent *) xevent);
+}
+
+void
+_ecore_x_event_handle_button_press(XEvent *xevent)
+{
+   int i;
+
+   _ecore_x_last_event_mouse_move = 0;
+   if ((xevent->xbutton.button > 3) && (xevent->xbutton.button < 8))
+     {
+       Ecore_Event_Mouse_Wheel *e;
+
+       e = malloc(sizeof(Ecore_Event_Mouse_Wheel));
+       if (!e) return;
+
+       e->timestamp = xevent->xbutton.time;
+       e->modifiers = _ecore_x_event_modifiers(xevent->xbutton.state);
+       switch (xevent->xbutton.button)
+         {
+          case 4: e->direction = 0; e->z = -1; break;
+          case 5: e->direction = 0; e->z = 1; break;
+          case 6: e->direction = 1; e->z = -1; break;
+          case 7: e->direction = 1; e->z = 1; break;
+           default: e->direction = 0; e->z = 0; break;
+         }
+
+       e->x = xevent->xbutton.x;
+       e->y = xevent->xbutton.y;
+       e->root.x = xevent->xbutton.x_root;
+       e->root.y = xevent->xbutton.y_root;
+
+       if (xevent->xbutton.subwindow) e->window = xevent->xbutton.subwindow;
+       else e->window = xevent->xbutton.window;
+       e->event_window = xevent->xbutton.window;
+       e->same_screen = xevent->xbutton.same_screen;
+       e->root_window = xevent->xbutton.root;
+
+       _ecore_x_event_last_time = e->timestamp;
+       _ecore_x_event_last_win = e->window;
+       _ecore_x_event_last_root_x = xevent->xbutton.x_root;
+       _ecore_x_event_last_root_y = xevent->xbutton.y_root;
+       ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
+
+       for (i = 0; i < _ecore_window_grabs_num; i++)
+         {
+            if ((_ecore_window_grabs[i] == xevent->xbutton.window) ||
+                (_ecore_window_grabs[i] == xevent->xbutton.subwindow))
+              {
+                 int replay = 0;
+
+                 if (_ecore_window_grab_replay_func)
+                   replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
+                                                           ECORE_EVENT_MOUSE_WHEEL,
+                                                           e);
+                 if (replay)
+                   XAllowEvents(xevent->xbutton.display,
+                                ReplayPointer, xevent->xbutton.time);
+                 else
+                   XAllowEvents(xevent->xbutton.display,
+                                AsyncPointer, xevent->xbutton.time);
+                 break;
+              }
+         }
+     }
+   else
+     {
+       {
+          _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state,
+                            xevent->xbutton.x, xevent->xbutton.y,
+                            xevent->xbutton.x_root, xevent->xbutton.y_root,
+                            xevent->xbutton.window,
+                            (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent->xbutton.window),
+                            xevent->xbutton.root,
+                            xevent->xbutton.same_screen,
+                             0, 1, 1,
+                             1.0, // pressure
+                             0.0, // angle
+                             xevent->xbutton.x, xevent->xbutton.y,
+                             xevent->xbutton.x_root, xevent->xbutton.y_root);
+       }
+       {
+          Ecore_Event_Mouse_Button *e;
+          int event_window;
+          int window;
+
+          if (_ecore_x_mouse_down_did_triple)
+            {
+               _ecore_x_mouse_down_last_win = 0;
+               _ecore_x_mouse_down_last_last_win = 0;
+               _ecore_x_mouse_down_last_event_win = 0;
+               _ecore_x_mouse_down_last_last_event_win = 0;
+               _ecore_x_mouse_down_last_time = 0;
+               _ecore_x_mouse_down_last_last_time = 0;
+            }
+
+          window = (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent->xbutton.window);
+          event_window = xevent->xbutton.window;
+
+          e = _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN,
+                                  xevent->xbutton.time, xevent->xbutton.state,
+                                  xevent->xbutton.button,
+                                  xevent->xbutton.x, xevent->xbutton.y,
+                                  xevent->xbutton.x_root, xevent->xbutton.y_root,
+                                  event_window, window,
+                                  xevent->xbutton.root, xevent->xbutton.same_screen,
+                                   0, 1, 1,
+                                   1.0, // pressure
+                                   0.0, // angle
+                                   xevent->xbutton.x, xevent->xbutton.y,
+                                   xevent->xbutton.x_root, xevent->xbutton.y_root);
+          if (e)
+            for (i = 0; i < _ecore_window_grabs_num; i++)
+              {
+                 if ((_ecore_window_grabs[i] == xevent->xbutton.window) ||
+                     (_ecore_window_grabs[i] == xevent->xbutton.subwindow))
+                   {
+                      int replay = 0;
+
+                      if (_ecore_window_grab_replay_func)
+                        replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
+                                                                ECORE_EVENT_MOUSE_BUTTON_DOWN,
+                                                                e);
+                      if (replay)
+                        XAllowEvents(xevent->xbutton.display,
+                                     ReplayPointer, xevent->xbutton.time);
+                      else
+                        XAllowEvents(xevent->xbutton.display,
+                                     AsyncPointer, xevent->xbutton.time);
+                      break;
+                   }
+              }
+
+          if (window == event_window)
+            {
+               if (!_ecore_x_mouse_down_did_triple)
+                 {
+                    _ecore_x_mouse_down_last_last_win = _ecore_x_mouse_down_last_win;
+                    if (xevent->xbutton.subwindow)
+                      _ecore_x_mouse_down_last_win = xevent->xbutton.subwindow;
+                    else
+                      _ecore_x_mouse_down_last_win = xevent->xbutton.window;
+                    _ecore_x_mouse_down_last_last_event_win = _ecore_x_mouse_down_last_event_win;
+                    _ecore_x_mouse_down_last_event_win = xevent->xbutton.window;
+                    _ecore_x_mouse_down_last_last_time = _ecore_x_mouse_down_last_time;
+                    _ecore_x_mouse_down_last_time = xevent->xbutton.time;
+                 }
+            }
+       }
+     }
+}
+
+void
+_ecore_x_event_handle_button_release(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   /* filter out wheel buttons */
+   if ((xevent->xbutton.button <= 3) || (xevent->xbutton.button > 7))
+     {
+       _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state,
+                         xevent->xbutton.x, xevent->xbutton.y,
+                         xevent->xbutton.x_root, xevent->xbutton.y_root,
+                         xevent->xbutton.window,
+                         (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent->xbutton.window),
+                         xevent->xbutton.root,
+                         xevent->xbutton.same_screen,
+                          0, 1, 1,
+                          1.0, // pressure
+                          0.0, // angle
+                          xevent->xbutton.x, xevent->xbutton.y,
+                          xevent->xbutton.x_root, xevent->xbutton.y_root);
+
+       _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
+                           xevent->xbutton.time, xevent->xbutton.state,
+                           xevent->xbutton.button,
+                           xevent->xbutton.x, xevent->xbutton.y,
+                           xevent->xbutton.x_root, xevent->xbutton.y_root,
+                           xevent->xbutton.window,
+                           (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent->xbutton.window),
+                           xevent->xbutton.root,
+                           xevent->xbutton.same_screen,
+                            0, 1, 1,
+                            1.0, // pressure
+                            0.0, // angle
+                            xevent->xbutton.x, xevent->xbutton.y,
+                            xevent->xbutton.x_root, xevent->xbutton.y_root);
+     }
+}
+
+void
+_ecore_x_event_handle_motion_notify(XEvent *xevent)
+{
+/*   
+   if (_ecore_x_last_event_mouse_move)
+     {
+        ecore_event_del(_ecore_x_last_event_mouse_move_event);
+        _ecore_x_last_event_mouse_move = 0;
+        _ecore_x_last_event_mouse_move_event = NULL;
+     }
+ */
+   _ecore_mouse_move(xevent->xmotion.time, xevent->xmotion.state,
+                    xevent->xmotion.x, xevent->xmotion.y,
+                    xevent->xmotion.x_root, xevent->xmotion.y_root,
+                    xevent->xmotion.window,
+                    (xevent->xmotion.subwindow ? xevent->xmotion.subwindow : xevent->xmotion.window),
+                    xevent->xmotion.root,
+                    xevent->xmotion.same_screen,
+                     0, 1, 1,
+                     1.0, // pressure
+                     0.0, // angle
+                     xevent->xmotion.x, xevent->xmotion.y,
+                     xevent->xmotion.x_root, xevent->xmotion.y_root);
+
+   _ecore_x_last_event_mouse_move = 1;
+
+   /* Xdnd handling */
+   _ecore_x_dnd_drag(xevent->xmotion.root, xevent->xmotion.x_root, xevent->xmotion.y_root);
+}
+
+void
+_ecore_x_event_handle_enter_notify(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+     {
+       _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state,
+                         xevent->xcrossing.x, xevent->xcrossing.y,
+                         xevent->xcrossing.x_root, xevent->xcrossing.y_root,
+                         xevent->xcrossing.window,
+                         (xevent->xcrossing.subwindow ? xevent->xcrossing.subwindow : xevent->xcrossing.window),
+                         xevent->xcrossing.root,
+                         xevent->xcrossing.same_screen,
+                          0, 1, 1,
+                          1.0, // pressure
+                          0.0, // angle
+                          xevent->xcrossing.x, xevent->xcrossing.y,
+                          xevent->xcrossing.x_root, xevent->xcrossing.y_root);
+     }
+     {
+       Ecore_X_Event_Mouse_In *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Mouse_In));
+       if (!e) return;
+       e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state);
+       e->x = xevent->xcrossing.x;
+       e->y = xevent->xcrossing.y;
+       e->root.x = xevent->xcrossing.x_root;
+       e->root.y = xevent->xcrossing.y_root;
+       if (xevent->xcrossing.subwindow) e->win = xevent->xcrossing.subwindow;
+       else e->win = xevent->xcrossing.window;
+       e->same_screen = xevent->xcrossing.same_screen;
+       e->root_win = xevent->xcrossing.root;
+       e->event_win = xevent->xcrossing.window;
+
+        if (xevent->xcrossing.mode == NotifyNormal) 
+          e->mode = ECORE_X_EVENT_MODE_NORMAL;
+       else if (xevent->xcrossing.mode == NotifyGrab) 
+          e->mode = ECORE_X_EVENT_MODE_GRAB;
+       else if (xevent->xcrossing.mode == NotifyUngrab) 
+          e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+
+       if (xevent->xcrossing.detail == NotifyAncestor) 
+          e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+       else if (xevent->xcrossing.detail == NotifyVirtual) 
+          e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+       else if (xevent->xcrossing.detail == NotifyInferior) 
+          e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+       else if (xevent->xcrossing.detail == NotifyNonlinear) 
+          e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+       else if (xevent->xcrossing.detail == NotifyNonlinearVirtual) 
+          e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+
+       e->time = xevent->xcrossing.time;
+       _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL);
+     }
+}
+
+void
+_ecore_x_event_handle_leave_notify(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+     {
+       _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state,
+                         xevent->xcrossing.x, xevent->xcrossing.y,
+                         xevent->xcrossing.x_root, xevent->xcrossing.y_root,
+                         xevent->xcrossing.window,
+                         (xevent->xcrossing.subwindow ? xevent->xcrossing.subwindow : xevent->xcrossing.window),
+                         xevent->xcrossing.root,
+                         xevent->xcrossing.same_screen,
+                          0, 1, 1,
+                          1.0, // pressure
+                          0.0, // angle
+                          xevent->xcrossing.x, xevent->xcrossing.y,
+                          xevent->xcrossing.x_root, xevent->xcrossing.y_root);
+     }
+     {
+       Ecore_X_Event_Mouse_Out *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out));
+       if (!e) return;
+       e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state);
+       e->x = xevent->xcrossing.x;
+       e->y = xevent->xcrossing.y;
+       e->root.x = xevent->xcrossing.x_root;
+       e->root.y = xevent->xcrossing.y_root;
+       if (xevent->xcrossing.subwindow) e->win = xevent->xcrossing.subwindow;
+       else e->win = xevent->xcrossing.window;
+       e->same_screen = xevent->xcrossing.same_screen;
+       e->root_win = xevent->xcrossing.root;
+       e->event_win = xevent->xcrossing.window;
+
+       if (xevent->xcrossing.mode == NotifyNormal) 
+          e->mode = ECORE_X_EVENT_MODE_NORMAL;
+       else if (xevent->xcrossing.mode == NotifyGrab) 
+          e->mode = ECORE_X_EVENT_MODE_GRAB;
+       else if (xevent->xcrossing.mode == NotifyUngrab) 
+          e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+
+       if (xevent->xcrossing.detail == NotifyAncestor) 
+          e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+       else if (xevent->xcrossing.detail == NotifyVirtual) 
+          e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+       else if (xevent->xcrossing.detail == NotifyInferior) 
+          e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+       else if (xevent->xcrossing.detail == NotifyNonlinear) 
+          e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+       else if (xevent->xcrossing.detail == NotifyNonlinearVirtual) 
+          e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+
+       e->time = xevent->xcrossing.time;
+       _ecore_x_event_last_time = e->time;
+       _ecore_x_event_last_win = e->win;
+       _ecore_x_event_last_root_x = e->root.x;
+       _ecore_x_event_last_root_y = e->root.y;
+       ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL);
+     }
+}
+
+void
+_ecore_x_event_handle_focus_in(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Focus_In *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   if (_ecore_x_ic)
+     {
+       char *str;
+
+       XSetICValues(_ecore_x_ic, XNFocusWindow, xevent->xfocus.window, NULL);
+       if ((str = XmbResetIC(_ecore_x_ic)))
+         XFree(str);
+       XSetICFocus(_ecore_x_ic);
+     }
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In));
+   if (!e) return;
+   e->win = xevent->xfocus.window;
+
+   if (xevent->xfocus.mode == NotifyNormal) 
+     e->mode = ECORE_X_EVENT_MODE_NORMAL;
+   else if (xevent->xfocus.mode == NotifyWhileGrabbed) 
+     e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
+   else if (xevent->xfocus.mode == NotifyGrab) 
+     e->mode = ECORE_X_EVENT_MODE_GRAB;
+   else if (xevent->xfocus.mode == NotifyUngrab) 
+     e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+
+   if (xevent->xfocus.detail == NotifyAncestor) 
+     e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+   else if (xevent->xfocus.detail == NotifyVirtual) 
+     e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+   else if (xevent->xfocus.detail == NotifyInferior) 
+     e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+   else if (xevent->xfocus.detail == NotifyNonlinear) 
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+   else if (xevent->xfocus.detail == NotifyNonlinearVirtual) 
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+   else if (xevent->xfocus.detail == NotifyPointer) 
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER;
+   else if (xevent->xfocus.detail == NotifyPointerRoot) 
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
+   else if (xevent->xfocus.detail == NotifyDetailNone) 
+     e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
+
+   e->time = _ecore_x_event_last_time;
+   _ecore_x_event_last_time = e->time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_focus_out(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Focus_Out *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   if (_ecore_x_ic) XUnsetICFocus(_ecore_x_ic);
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out));
+   if (!e) return;
+   e->win = xevent->xfocus.window;
+
+   if (xevent->xfocus.mode == NotifyNormal) 
+     e->mode = ECORE_X_EVENT_MODE_NORMAL;
+   else if (xevent->xfocus.mode == NotifyWhileGrabbed) 
+     e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
+   else if (xevent->xfocus.mode == NotifyGrab) 
+     e->mode = ECORE_X_EVENT_MODE_GRAB;
+   else if (xevent->xfocus.mode == NotifyUngrab) 
+     e->mode = ECORE_X_EVENT_MODE_UNGRAB;
+
+   if (xevent->xfocus.detail == NotifyAncestor) 
+     e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
+   else if (xevent->xfocus.detail == NotifyVirtual) 
+     e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
+   else if (xevent->xfocus.detail == NotifyInferior) 
+     e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
+   else if (xevent->xfocus.detail == NotifyNonlinear) 
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
+   else if (xevent->xfocus.detail == NotifyNonlinearVirtual) 
+     e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
+   else if (xevent->xfocus.detail == NotifyPointer) 
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER;
+   else if (xevent->xfocus.detail == NotifyPointerRoot) 
+     e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
+   else if (xevent->xfocus.detail == NotifyDetailNone) 
+     e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
+
+   e->time = _ecore_x_event_last_time;
+   _ecore_x_event_last_time = e->time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_keymap_notify(XEvent *xevent __UNUSED__)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   /* FIXME: handle this event type */   
+}
+
+void
+_ecore_x_event_handle_expose(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Damage *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
+   if (!e) return;
+   e->win = xevent->xexpose.window;
+   e->time = _ecore_x_event_last_time;
+   e->x = xevent->xexpose.x;
+   e->y = xevent->xexpose.y;
+   e->w = xevent->xexpose.width;
+   e->h = xevent->xexpose.height;
+   e->count = xevent->xexpose.count;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);   
+}
+
+void
+_ecore_x_event_handle_graphics_expose(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Damage *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
+   if (!e) return;
+   e->win = xevent->xgraphicsexpose.drawable;
+   e->time = _ecore_x_event_last_time;
+   e->x = xevent->xgraphicsexpose.x;
+   e->y = xevent->xgraphicsexpose.y;
+   e->w = xevent->xgraphicsexpose.width;
+   e->h = xevent->xgraphicsexpose.height;
+   e->count = xevent->xgraphicsexpose.count;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);   
+}
+
+void
+_ecore_x_event_handle_visibility_notify(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+//   if (xevent->xvisibility.state != VisibilityPartiallyObscured)
+   {
+      Ecore_X_Event_Window_Visibility_Change *e;
+
+      e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change));
+      if (!e) return;
+      e->win = xevent->xvisibility.window;
+      e->time = _ecore_x_event_last_time;
+      if (xevent->xvisibility.state == VisibilityFullyObscured)
+        e->fully_obscured = 1;
+      else
+        e->fully_obscured = 0;     
+      ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_x_event_handle_create_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Create *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Create));
+   if (!e) return;
+   e->win = xevent->xcreatewindow.window;
+   e->parent = xevent->xcreatewindow.parent;
+   if (xevent->xcreatewindow.override_redirect)
+     e->override = 1;
+   else
+     e->override = 0;
+   e->x = xevent->xcreatewindow.x;
+   e->y = xevent->xcreatewindow.y;
+   e->w = xevent->xcreatewindow.width;
+   e->h = xevent->xcreatewindow.height;
+   e->border = xevent->xcreatewindow.border_width;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_destroy_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Destroy *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy));
+   if (!e) return;
+   e->win =  xevent->xdestroywindow.window;
+   e->event_win = xevent->xdestroywindow.event;
+   e->time = _ecore_x_event_last_time;
+   if (e->win == _ecore_x_event_last_win) _ecore_x_event_last_win = 0;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL);   
+}
+
+void
+_ecore_x_event_handle_unmap_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Hide *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Hide));
+   if (!e) return;
+   e->win = xevent->xunmap.window;
+   e->event_win = xevent->xunmap.event;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_map_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Show *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Show));
+   if (!e) return;
+   e->win = xevent->xmap.window;
+   e->event_win = xevent->xmap.event;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_map_request(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Show_Request *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request));
+   if (!e) return;
+   e->win = xevent->xmaprequest.window;
+   e->time = _ecore_x_event_last_time;
+   e->parent = xevent->xmaprequest.parent;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_reparent_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Reparent *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent));
+   if (!e) return;
+   e->win = xevent->xreparent.window;
+   e->event_win = xevent->xreparent.event;
+   e->parent = xevent->xreparent.parent;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_configure_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Configure *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Configure));
+   if (!e) return;
+   e->win = xevent->xconfigure.window;
+   e->event_win = xevent->xconfigure.event;
+   e->abovewin = xevent->xconfigure.above;
+   e->x = xevent->xconfigure.x;
+   e->y = xevent->xconfigure.y;
+   e->w = xevent->xconfigure.width;
+   e->h = xevent->xconfigure.height;
+   e->border = xevent->xconfigure.border_width;
+   e->override = xevent->xconfigure.override_redirect;
+   e->from_wm = xevent->xconfigure.send_event;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL);      
+}
+
+void
+_ecore_x_event_handle_configure_request(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Configure_Request *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request));
+   if (!e) return;
+   e->win = xevent->xconfigurerequest.window;
+   e->parent_win = xevent->xconfigurerequest.parent;
+   e->abovewin = xevent->xconfigurerequest.above;
+   e->x = xevent->xconfigurerequest.x;
+   e->y = xevent->xconfigurerequest.y;
+   e->w = xevent->xconfigurerequest.width;
+   e->h = xevent->xconfigurerequest.height;
+   e->border = xevent->xconfigurerequest.border_width;
+   e->value_mask = xevent->xconfigurerequest.value_mask;
+   e->time = _ecore_x_event_last_time;
+
+   if (xevent->xconfigurerequest.detail == Above)
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+   else if (xevent->xconfigurerequest.detail == Below)
+     e->detail = ECORE_X_WINDOW_STACK_BELOW;
+   else if (xevent->xconfigurerequest.detail == TopIf)
+     e->detail = ECORE_X_WINDOW_STACK_TOP_IF;
+   else if (xevent->xconfigurerequest.detail == BottomIf)
+     e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF;
+   else if (xevent->xconfigurerequest.detail == Opposite)
+     e->detail = ECORE_X_WINDOW_STACK_OPPOSITE;
+
+   ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_gravity_notify(XEvent *xevent __UNUSED__)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   /* FIXME: handle this event type */
+}
+
+void
+_ecore_x_event_handle_resize_request(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Resize_Request *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request));
+   if (!e) return;
+   e->win = xevent->xresizerequest.window;
+   e->w = xevent->xresizerequest.width;
+   e->h = xevent->xresizerequest.height;
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_circulate_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Stack *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Stack));
+   if (!e) return;
+   e->win = xevent->xcirculate.window;
+   e->event_win = xevent->xcirculate.event;
+   if (xevent->xcirculate.place == PlaceOnTop)
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+   else
+     e->detail = ECORE_X_WINDOW_STACK_BELOW; 
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_circulate_request(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Stack_Request *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request));
+   if (!e) return;
+   e->win = xevent->xcirculaterequest.window;
+   e->parent = xevent->xcirculaterequest.parent;
+   if (xevent->xcirculaterequest.place == PlaceOnTop)
+     e->detail = ECORE_X_WINDOW_STACK_ABOVE;
+   else
+     e->detail = ECORE_X_WINDOW_STACK_BELOW; 
+   e->time = _ecore_x_event_last_time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_property_notify(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+#if 0 /* for now i disabled this. nice idea though this is - it leaves a lot
+       * to be desired for efficiency that is better left to the app layer
+       */
+   if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLASS)
+     {
+       Ecore_X_Event_Window_Prop_Name_Class_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Name_Class_Change));
+       if (!e) return;
+       ecore_x_window_prop_name_class_get(xevent->xproperty.window, 
+                                          &(e->name), &(e->clas));
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_name_class_change, NULL);
+     }
+   else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_NAME) || 
+            (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_NAME))
+     {
+       Ecore_X_Event_Window_Prop_Title_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Title_Change));
+       if (!e) return;
+       e->title = ecore_x_window_prop_title_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_title_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_NAME)
+     {
+       Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Title_Change));
+       if (!e) return;
+       e->title = ecore_x_window_prop_visible_title_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_visible_title_change, NULL);
+     }
+   else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_ICON_NAME) || 
+            (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_ICON_NAME))
+     {
+       Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Icon_Name_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_icon_name_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_icon_name_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME)
+     {
+       Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_visible_icon_name_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_visible_icon_name_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
+     {
+       Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Client_Machine_Change));
+       if (!e) return;
+       e->name = ecore_x_window_prop_client_machine_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, e, 
+                        _ecore_x_event_free_window_prop_client_machine_change, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_PID)
+     {
+       Ecore_X_Event_Window_Prop_Pid_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Pid_Change));
+       if (!e) return;
+       e->pid = ecore_x_window_prop_pid_get(xevent->xproperty.window);
+        e->time = xevent->xproperty.time;
+        _ecore_x_event_last_time = e->time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
+     }
+   else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_DESKTOP)
+     {
+       Ecore_X_Event_Window_Prop_Desktop_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Desktop_Change));
+       if (!e) return;
+       e->desktop = ecore_x_window_prop_desktop_get(xevent->xproperty.window);
+       ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
+     }
+   else 
+#endif     
+   {
+      Ecore_X_Event_Window_Property *e;
+
+      e = calloc(1, sizeof(Ecore_X_Event_Window_Property));
+      if (!e) return;
+      e->win = xevent->xproperty.window;
+      e->atom = xevent->xproperty.atom;
+      e->time = xevent->xproperty.time;
+      _ecore_x_event_last_time = e->time;
+      ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL);
+   }
+}
+
+void
+_ecore_x_event_handle_selection_clear(XEvent *xevent)
+{
+   Ecore_X_Selection_Intern *d;
+   Ecore_X_Event_Selection_Clear *e;
+   Ecore_X_Atom sel;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_last_event_mouse_move = 0;
+   d = _ecore_x_selection_get(xevent->xselectionclear.selection);
+   if (d && (xevent->xselectionclear.time > d->time))
+     {
+       _ecore_x_selection_set(None, NULL, 0, 
+                              xevent->xselectionclear.selection);
+     }
+
+   /* Generate event for app cleanup */
+   e = malloc(sizeof(Ecore_X_Event_Selection_Clear));
+   e->win = xevent->xselectionclear.window;
+   e->time = xevent->xselectionclear.time;
+   e->atom = sel = xevent->xselectionclear.selection;
+   if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
+     e->selection = ECORE_X_SELECTION_PRIMARY;
+   else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
+     e->selection = ECORE_X_SELECTION_SECONDARY;
+   else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     e->selection = ECORE_X_SELECTION_CLIPBOARD;
+   else
+     e->selection = ECORE_X_SELECTION_OTHER;
+   ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_selection_request(XEvent *xevent)
+{
+   Ecore_X_Event_Selection_Request *e;
+   Ecore_X_Selection_Intern *sd;
+   void *data;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_last_event_mouse_move = 0;
+   /*
+    * Generate a selection request event.
+    */
+   e = malloc(sizeof(Ecore_X_Event_Selection_Request));
+   e->owner = xevent->xselectionrequest.owner;
+   e->requestor = xevent->xselectionrequest.requestor;
+   e->time = xevent->xselectionrequest.time;
+   e->selection = xevent->xselectionrequest.selection;
+   e->target = xevent->xselectionrequest.target;
+   e->property = xevent->xselectionrequest.property;
+   ecore_event_add(ECORE_X_EVENT_SELECTION_REQUEST, e, NULL, NULL);
+
+   if ((sd = _ecore_x_selection_get(xevent->xselectionrequest.selection)) &&
+       (sd->win == xevent->xselectionrequest.owner))
+     {
+       Ecore_X_Selection_Intern *si;
+
+       si = _ecore_x_selection_get(xevent->xselectionrequest.selection);
+       if (si->data)
+         {
+            Ecore_X_Atom property;
+
+            if (!ecore_x_selection_convert(xevent->xselectionrequest.selection,
+                                           xevent->xselectionrequest.target,
+                                           &data))
+              {
+                 /* Refuse selection, conversion to requested target failed */
+                 property = None;
+              }
+            else
+              {
+                 /* FIXME: This does not properly handle large data transfers */
+                 ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor,
+                                                  xevent->xselectionrequest.property,
+                                                  xevent->xselectionrequest.target,
+                                                  8, data, sd->length);
+                 property = xevent->xselectionrequest.property;
+                 free(data);
+              }
+
+            ecore_x_selection_notify_send(xevent->xselectionrequest.requestor,
+                                          xevent->xselectionrequest.selection,
+                                          xevent->xselectionrequest.target,
+                                          property,
+                                          xevent->xselectionrequest.time);
+         }
+     }
+   return;
+}
+
+void
+_ecore_x_event_handle_selection_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Selection_Notify *e;
+   unsigned char *data = NULL;
+   Ecore_X_Atom selection;
+   int num_ret, format;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_last_event_mouse_move = 0;
+   selection = xevent->xselection.selection;
+
+   if (xevent->xselection.target == ECORE_X_ATOM_SELECTION_TARGETS)
+     {
+       format = ecore_x_window_prop_property_get(xevent->xselection.requestor,
+                                               xevent->xselection.property,
+                                               XA_ATOM, 32, &data, &num_ret);
+       if (!format) return;
+     }
+   else
+     {
+       format = ecore_x_window_prop_property_get(xevent->xselection.requestor,
+                                               xevent->xselection.property,
+                                               AnyPropertyType, 8, &data,
+                                               &num_ret);
+       if (!format) return;
+     }
+
+   e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify));
+   if (!e) return;
+   e->win = xevent->xselection.requestor;
+   e->time = xevent->xselection.time;
+   e->atom = selection;
+   e->target = _ecore_x_selection_target_get(xevent->xselection.target);
+
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     e->selection = ECORE_X_SELECTION_PRIMARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     e->selection = ECORE_X_SELECTION_SECONDARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     e->selection = ECORE_X_SELECTION_XDND;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     e->selection = ECORE_X_SELECTION_CLIPBOARD;
+   else
+     e->selection = ECORE_X_SELECTION_OTHER;
+
+   e->data = _ecore_x_selection_parse(e->target, data, num_ret, format);
+
+   ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, 
+                   _ecore_x_event_free_selection_notify, NULL);
+}
+
+void
+_ecore_x_event_handle_colormap_notify(XEvent *xevent)
+{
+   Ecore_X_Event_Window_Colormap *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   e = calloc(1,sizeof(Ecore_X_Event_Window_Colormap));
+   if (!e) return;
+   e->win = xevent->xcolormap.window;
+   e->cmap = xevent->xcolormap.colormap;
+   e->time = _ecore_x_event_last_time;
+   if (xevent->xcolormap.state == ColormapInstalled)
+      e->installed = 1;
+   else
+      e->installed = 0;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_client_message(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   /* Special client message event handling here. need to put LOTS of if */
+   /* checks here and generate synthetic events per special message known */
+   /* otherwise generate generic client message event. this would handle*/
+   /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */
+   if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS) &&
+       (xevent->xclient.format == 32) &&
+       (xevent->xclient.data.l[0] == (long)ECORE_X_ATOM_WM_DELETE_WINDOW))
+     {
+       Ecore_X_Event_Window_Delete_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->time = _ecore_x_event_last_time;
+       ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
+     }
+
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_MOVERESIZE) &&
+           (xevent->xclient.format == 32) &&
+           /* Ignore move and resize with keyboard */
+           (xevent->xclient.data.l[2] < 9))
+     {
+       Ecore_X_Event_Window_Move_Resize_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->x = xevent->xclient.data.l[0];
+       e->y = xevent->xclient.data.l[1];
+       e->direction = xevent->xclient.data.l[2];
+       e->button = xevent->xclient.data.l[3];
+       e->source = xevent->xclient.data.l[4];
+       ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL);
+     }
+
+   /* Xdnd Client Message Handling Begin */
+   /* Message Type: XdndEnter target */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_ENTER)
+     {
+       Ecore_X_Event_Xdnd_Enter *e;
+       Ecore_X_DND_Target *target;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter));
+       if (!e) return;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       target = _ecore_x_dnd_target_get();
+       target->state = ECORE_X_DND_TARGET_ENTERED;
+       target->source = xevent->xclient.data.l[0];
+       target->win = xevent->xclient.window;
+       target->version = (int) (xevent->xclient.data.l[1] >> 24);
+       if (target->version > ECORE_X_DND_VERSION)
+         {
+            WRN("DND: Requested version %d, we only support up to %d", 
+                    target->version, ECORE_X_DND_VERSION);
+            return;
+         }
+
+       if (xevent->xclient.data.l[1] & 0x1UL)
+         {
+            /* source supports more than 3 types, fetch property */
+            unsigned char *data;
+            Ecore_X_Atom *types;
+            int i, num_ret;
+
+             LOGFN(__FILE__, __LINE__, __FUNCTION__);
+            if (!(ecore_x_window_prop_property_get(target->source, 
+                                                   ECORE_X_ATOM_XDND_TYPE_LIST,
+                                                   XA_ATOM,
+                                                   32, &data, &num_ret)))
+              {
+                 WRN("DND: Could not fetch data type list from source window, aborting.");
+                 return;
+              }
+            types = (Ecore_X_Atom *)data;
+            e->types = calloc(num_ret, sizeof(char *));
+            if (e->types)
+              {
+                  LOGFN(__FILE__, __LINE__, __FUNCTION__);
+                 for (i = 0; i < num_ret; i++)
+                   e->types[i] = XGetAtomName(_ecore_x_disp, types[i]);
+              }
+            e->num_types = num_ret;
+         }
+       else
+         {
+            int i = 0;
+
+            e->types = calloc(3, sizeof(char *));
+            if (e->types)
+              {
+                  LOGFN(__FILE__, __LINE__, __FUNCTION__);
+                 while ((i < 3) && (xevent->xclient.data.l[i + 2]))
+                   {
+                      e->types[i] = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[i + 2]);
+                      i++;
+                   }
+              }
+            e->num_types = i;
+         }
+
+       e->win = target->win;
+       e->source = target->source;
+       ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, 
+                        _ecore_x_event_free_xdnd_enter, NULL);
+     }
+
+   /* Message Type: XdndPosition target */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_POSITION)
+     {
+       Ecore_X_Event_Xdnd_Position *e;
+       Ecore_X_DND_Target *target;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       target = _ecore_x_dnd_target_get();
+       if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) ||
+           (target->win != xevent->xclient.window))
+         return;
+
+       target->pos.x = xevent->xclient.data.l[2] >> 16;
+       target->pos.y = xevent->xclient.data.l[2] & 0xFFFFUL;
+       target->action = xevent->xclient.data.l[4]; /* Version 2 */
+
+       target->time = (target->version >= 1) ? 
+          (Time)xevent->xclient.data.l[3] : CurrentTime;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position));
+       if (!e) return;
+       e->win = target->win;
+       e->source = target->source;
+       e->position.x = target->pos.x;
+       e->position.y = target->pos.y;
+       e->action = target->action;
+       ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndStatus source */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_STATUS)
+     {
+       Ecore_X_Event_Xdnd_Status *e;
+       Ecore_X_DND_Source *source;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       source = _ecore_x_dnd_source_get();
+       /* Make sure source/target match */
+       if ((source->win != xevent->xclient.window ) ||
+           (source->dest != (Window)xevent->xclient.data.l[0]))
+         return;
+
+       source->await_status = 0;
+
+       source->will_accept = xevent->xclient.data.l[1] & 0x1UL;
+       source->suppress = (xevent->xclient.data.l[1] & 0x2UL) ? 0 : 1;
+
+       source->rectangle.x = xevent->xclient.data.l[2] >> 16;
+       source->rectangle.y = xevent->xclient.data.l[2] & 0xFFFFUL;
+       source->rectangle.width = xevent->xclient.data.l[3] >> 16;
+       source->rectangle.height = xevent->xclient.data.l[3] & 0xFFFFUL;
+
+       source->accepted_action = xevent->xclient.data.l[4];
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status));
+       if (!e) return;
+       e->win = source->win;
+       e->target = source->dest;
+       e->will_accept = source->will_accept;
+       e->rectangle.x = source->rectangle.x;
+       e->rectangle.y = source->rectangle.y;
+       e->rectangle.width = source->rectangle.width;
+       e->rectangle.height = source->rectangle.height;
+       e->action = source->accepted_action;
+
+       ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndLeave target */
+   /* Pretend the whole thing never happened, sort of */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_LEAVE)
+     {
+       Ecore_X_Event_Xdnd_Leave *e;
+       Ecore_X_DND_Target *target;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       target = _ecore_x_dnd_target_get();
+       if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) ||
+           (target->win != xevent->xclient.window))
+         return;
+
+       target->state = ECORE_X_DND_TARGET_IDLE;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->source = (Window)xevent->xclient.data.l[0];
+       ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL);
+     }
+
+   /* Message Type: XdndDrop target */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_DROP)
+     {
+       Ecore_X_Event_Xdnd_Drop *e;
+       Ecore_X_DND_Target *target;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       target = _ecore_x_dnd_target_get();
+       /* Match source/target */
+       if ((target->source != (Window)xevent->xclient.data.l[0]) ||
+           (target->win != xevent->xclient.window))
+         return;
+
+       target->time = (target->version >= 1) ? 
+          (Time)xevent->xclient.data.l[2] : _ecore_x_event_last_time;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop));
+       if (!e) return;
+       e->win = target->win;
+       e->source = target->source;
+       e->action = target->action;
+       e->position.x = target->pos.x;
+       e->position.y = target->pos.y;
+       ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL);
+     }
+
+  /* Message Type: XdndFinished source */
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_FINISHED)
+     {
+       Ecore_X_Event_Xdnd_Finished *e;
+       Ecore_X_DND_Source *source;
+       int completed = 1;
+
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       source = _ecore_x_dnd_source_get();
+       /* Match source/target */
+       if ((source->win != xevent->xclient.window) ||
+           (source->dest != (Window)xevent->xclient.data.l[0]))
+         return;
+
+       if ((source->version < 5) || (xevent->xclient.data.l[1] & 0x1UL))
+         {
+             LOGFN(__FILE__, __LINE__, __FUNCTION__);
+            /* Target successfully performed drop action */
+            ecore_x_selection_xdnd_clear();
+            source->state = ECORE_X_DND_SOURCE_IDLE;
+         }
+       else if (source->version >= 5)
+         {
+              completed = 0;
+              source->state = ECORE_X_DND_SOURCE_CONVERTING;
+
+              /* FIXME: Probably need to add a timer to switch back to idle 
+               * and discard the selection data */
+         } 
+
+       e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished));
+       if (!e) return;
+       e->win = source->win;
+       e->target = source->dest;
+       e->completed = completed;
+       if (source->version >= 5)
+         {
+            source->accepted_action = xevent->xclient.data.l[2];
+            e->action = source->accepted_action;
+         }
+       else
+         {
+            source->accepted_action = 0;
+            e->action = source->action;
+         }
+
+       ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL);
+     }
+   else if (xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_STATE)
+     {
+       Ecore_X_Event_Window_State_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       if (xevent->xclient.data.l[0] == 0)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE;
+       else if (xevent->xclient.data.l[0] == 1)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
+       else if (xevent->xclient.data.l[0] == 2)
+         e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE;
+       else
+         {
+            free(e);
+            return;
+         }
+        LOGFN(__FILE__, __LINE__, __FUNCTION__);
+       e->state[0] = _ecore_x_netwm_state_get(xevent->xclient.data.l[1]);
+       if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN)
+         {
+//          char *name;
+
+             LOGFN(__FILE__, __LINE__, __FUNCTION__);
+//          name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[1]);
+//          if (name) ERR("Unknown state: %s", name);
+//          XFree(name);
+         }
+       e->state[1] = _ecore_x_netwm_state_get(xevent->xclient.data.l[2]);
+       if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN)
+         {
+//          char *name;
+
+             LOGFN(__FILE__, __LINE__, __FUNCTION__);
+//          name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[2]);
+//          if (name) ERR("Unknown state: %s", name);
+//          XFree(name);
+         }
+       e->source = xevent->xclient.data.l[3];
+
+       ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_CHANGE_STATE)
+           && (xevent->xclient.format == 32)
+           && (xevent->xclient.data.l[0] == IconicState))
+     {
+       Ecore_X_Event_Window_State_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
+       e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED;
+
+       ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_DESKTOP)
+           && (xevent->xclient.format == 32))
+     {
+       Ecore_X_Event_Desktop_Change *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->desk = xevent->xclient.data.l[0];
+       e->source = xevent->xclient.data.l[1];
+
+       ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL);
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS))
+     {
+       Ecore_X_Event_Frame_Extents_Request *e;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+
+       ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL);
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS)
+           && ((Ecore_X_Atom)xevent->xclient.data.l[0] == ECORE_X_ATOM_NET_WM_PING)
+           && (xevent->xclient.format == 32))
+     {
+       Ecore_X_Event_Ping *e;
+        Ecore_X_Window root = 0;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Ping));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->time = xevent->xclient.data.l[1];
+       e->event_win = xevent->xclient.data.l[2];
+
+        /* send a reply anyway - we are alive... eventloop at least */
+       ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL);
+        if (ScreenCount(_ecore_x_disp) > 1)
+          {
+             LOGFN(__FILE__, __LINE__, __FUNCTION__);
+             root = ecore_x_window_root_get(e->win);
+          }
+        else
+          root = DefaultRootWindow(_ecore_x_disp);
+
+        if (xevent->xclient.window != root)
+          {
+             xevent->xclient.window = root;
+             XSendEvent(_ecore_x_disp, root, False, 
+                        SubstructureRedirectMask | SubstructureNotifyMask, 
+                        xevent);
+          }
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) &&
+           (xevent->xclient.format == 8))
+     {
+       _ecore_x_netwm_startup_info_begin(xevent->xclient.window, xevent->xclient.data.b);
+     }
+   else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_STARTUP_INFO) &&
+           (xevent->xclient.format == 8))
+     {
+       _ecore_x_netwm_startup_info(xevent->xclient.window, xevent->xclient.data.b);
+     }
+   else if ((xevent->xclient.message_type == 27777)
+           && (xevent->xclient.data.l[0] == 0x7162534)
+           && (xevent->xclient.format == 32)
+           && (xevent->xclient.window == _ecore_x_private_win))
+     {
+       /* a grab sync marker */
+       if (xevent->xclient.data.l[1] == 0x10000001)
+         _ecore_x_window_grab_remove(xevent->xclient.data.l[2]);
+       else if (xevent->xclient.data.l[1] == 0x10000002)
+         _ecore_x_key_grab_remove(xevent->xclient.data.l[2]);
+     }
+   else
+     {
+       Ecore_X_Event_Client_Message *e;
+       int i;
+
+       e = calloc(1, sizeof(Ecore_X_Event_Client_Message));
+       if (!e) return;
+       e->win = xevent->xclient.window;
+       e->message_type = xevent->xclient.message_type;
+       e->format = xevent->xclient.format;
+       for (i = 0; i < 5; i++) 
+         e->data.l[i] = xevent->xclient.data.l[i];
+
+       ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL);
+     }
+}
+
+void
+_ecore_x_event_handle_mapping_notify(XEvent *xevent)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   XRefreshKeyboardMapping((XMappingEvent *)xevent);
+}
+
+void
+_ecore_x_event_handle_shape_change(XEvent *xevent)
+{
+   XShapeEvent *shape_event;
+   Ecore_X_Event_Window_Shape *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   shape_event = (XShapeEvent *)xevent;
+   e = calloc(1, sizeof(Ecore_X_Event_Window_Shape));
+   if (!e) return;
+   e->win = shape_event->window;
+   e->time = shape_event->time;
+   ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_screensaver_notify(XEvent *xevent)
+{
+#ifdef ECORE_XSS
+   XScreenSaverNotifyEvent *screensaver_event;
+   Ecore_X_Event_Screensaver_Notify *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   screensaver_event = (XScreenSaverNotifyEvent *)xevent;
+   e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify));
+   if (!e) return;
+   e->win = screensaver_event->window;
+   if (screensaver_event->state == ScreenSaverOn)
+     e->on = 1;
+  else 
+     e->on = 0;
+   e->time = screensaver_event->time;
+   ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL);
+#else
+   xevent = NULL;
+#endif   
+}
+
+void
+_ecore_x_event_handle_sync_counter(XEvent *xevent)
+{
+   XSyncCounterNotifyEvent *sync_counter_event;
+   Ecore_X_Event_Sync_Counter *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   sync_counter_event = (XSyncCounterNotifyEvent *)xevent;
+   e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter));
+   if (!e) return;
+   e->time = sync_counter_event->time;
+   ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_sync_alarm(XEvent *xevent)
+{
+   XSyncAlarmNotifyEvent *sync_alarm_event;
+   Ecore_X_Event_Sync_Alarm *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   sync_alarm_event = (XSyncAlarmNotifyEvent *)xevent;
+
+   e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm));
+   if (!e) return;
+   e->time = sync_alarm_event->time;
+   e->alarm = sync_alarm_event->alarm;
+   ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL);
+}
+
+#ifdef ECORE_XRANDR
+void
+_ecore_x_event_handle_randr_change(XEvent *xevent)
+{
+   XRRScreenChangeNotifyEvent *randr_event;
+   Ecore_X_Event_Screen_Change *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   randr_event = (XRRScreenChangeNotifyEvent *)xevent;
+   if (!XRRUpdateConfiguration(xevent))
+     ERR("Can't update RR config!");
+
+   e = calloc(1, sizeof(Ecore_X_Event_Screen_Change));
+   if (!e) return;
+   e->win = randr_event->window;
+   e->root = randr_event->root;
+   e->width = randr_event->width;
+   e->height = randr_event->height;
+   e->time = randr_event->timestamp;
+   e->config_time = randr_event->config_timestamp;
+   e->mm_width = randr_event->mwidth;
+   e->mm_height = randr_event->mheight;
+   e->rotation = randr_event->rotation;
+   e->subpixel_order = randr_event->subpixel_order;
+   ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL);
+}
+
+static void
+_ecore_x_event_handle_randr_notify_crtc_change(const XRRNotifyEvent *xevent)
+{
+   const XRRCrtcChangeNotifyEvent *randr_event;
+   Ecore_X_Event_Randr_Crtc_Change *e;
+
+   randr_event = (const XRRCrtcChangeNotifyEvent *)xevent;
+
+   e = calloc(1, sizeof(Ecore_X_Event_Randr_Crtc_Change));
+   if (!e) return;
+   e->win = randr_event->window;
+   e->crtc = randr_event->crtc;
+   e->mode = randr_event->mode;
+   e->rotation = randr_event->rotation;
+   e->x = randr_event->x;
+   e->y = randr_event->y;
+   e->width = randr_event->width;
+   e->height = randr_event->height;
+   ecore_event_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, e, NULL, NULL);
+}
+
+static void
+_ecore_x_event_handle_randr_notify_output_change(const XRRNotifyEvent *xevent)
+{
+   const XRROutputChangeNotifyEvent *randr_event;
+   Ecore_X_Event_Randr_Output_Change *e;
+
+   randr_event = (const XRROutputChangeNotifyEvent *)xevent;
+
+   e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Change));
+   if (!e) return;
+   e->win = randr_event->window;
+   e->output = randr_event->output;
+   e->crtc = randr_event->crtc;
+   e->mode = randr_event->mode;
+   e->rotation = randr_event->rotation;
+   e->connection = randr_event->connection;
+   e->subpixel_order = randr_event->subpixel_order;
+   ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, e, NULL, NULL);
+}
+
+static void
+_ecore_x_event_handle_randr_notify_output_property(const XRRNotifyEvent *xevent)
+{
+   const XRROutputPropertyNotifyEvent *randr_event;
+   Ecore_X_Event_Randr_Output_Property_Notify *e;
+
+   randr_event = (const XRROutputPropertyNotifyEvent *)xevent;
+
+   e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Property_Notify));
+   if (!e) return;
+   e->win = randr_event->window;
+   e->output = randr_event->output;
+   e->property = randr_event->property;
+   e->time = randr_event->timestamp;
+   e->state = randr_event->state;
+   ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, e, NULL, NULL);
+}
+
+void
+_ecore_x_event_handle_randr_notify(XEvent *xevent)
+{
+   const XRRNotifyEvent *randr_event;
+
+   _ecore_x_last_event_mouse_move = 0;
+   randr_event = (const XRRNotifyEvent *)xevent;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   switch (randr_event->subtype)
+     {
+      case RRNotify_CrtcChange:
+        _ecore_x_event_handle_randr_notify_crtc_change(randr_event);
+        break;
+      case RRNotify_OutputChange:
+        _ecore_x_event_handle_randr_notify_output_change(randr_event);
+        break;
+      case RRNotify_OutputProperty:
+        _ecore_x_event_handle_randr_notify_output_property(randr_event);
+        break;
+      default:
+        ERR("Unknown XRandR RRNotify subtype: %d.",
+            randr_event->subtype);
+        break;
+     }
+}
+#endif
+
+#ifdef ECORE_XFIXES
+void
+_ecore_x_event_handle_fixes_selection_notify(XEvent *event)
+{
+   _ecore_x_last_event_mouse_move = 0;
+   /* Nothing here yet */
+   event = NULL;
+}
+#endif
+
+#ifdef ECORE_XDAMAGE
+void
+_ecore_x_event_handle_damage_notify(XEvent *event)
+{
+   XDamageNotifyEvent *damage_event;
+   Ecore_X_Event_Damage *e;
+
+   _ecore_x_last_event_mouse_move = 0;
+   damage_event = (XDamageNotifyEvent *)event;
+
+   e = calloc(1, sizeof(Ecore_X_Event_Damage));
+   if (!e) return;
+
+   e->level = damage_event->level;
+   e->drawable = damage_event->drawable;
+   e->damage = damage_event->damage;
+   e->more = damage_event->more;
+   e->time = damage_event->timestamp;
+   e->area.x = damage_event->area.x;
+   e->area.y = damage_event->area.y;
+   e->area.width = damage_event->area.width;
+   e->area.height = damage_event->area.height;
+   e->geometry.x = damage_event->geometry.x;
+   e->geometry.y = damage_event->geometry.y;
+   e->geometry.width = damage_event->geometry.width;
+   e->geometry.height = damage_event->geometry.height;
+
+   ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL);
+}
+#endif
+
+static void
+_ecore_x_event_free_generic_event(void *data, void *ev)
+{
+#ifdef ECORE_XI2
+   Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic*)ev;
+   
+   if (e->data)
+     {
+        XFreeEventData(_ecore_x_disp, (XGenericEventCookie *)data);
+     }
+#endif   
+}
+
+void
+_ecore_x_event_handle_generic_event(XEvent *event)
+{
+#ifdef ECORE_XI2
+   XGenericEvent *generic_event;
+   Ecore_X_Event_Generic *e;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   generic_event = (XGenericEvent *)event;
+   
+   e = calloc(1, sizeof(Ecore_X_Event_Generic));
+   if (!e) return;
+   
+   if (XGetEventData(_ecore_x_disp, &event->xcookie))
+     {
+        e->cookie = event->xcookie.cookie;
+        e->data = event->xcookie.data;
+     }
+   else
+     {
+        e->cookie = 0;
+        e->data = NULL;
+     }
+   
+   e->extension = generic_event->extension;
+   e->evtype = generic_event->evtype;
+   
+   if (e->extension == _ecore_x_xi2_opcode)
+     {
+        _ecore_x_input_handler(event);
+     }
+   
+   ecore_event_add(ECORE_X_EVENT_GENERIC, e, _ecore_x_event_free_generic_event, event);
+#endif   
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_fixes.c b/src/lib/ecore_x/xlib/ecore_x_fixes.c
new file mode 100644 (file)
index 0000000..ce2d19d
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+static int _fixes_available;
+#ifdef ECORE_XFIXES
+static int _fixes_major, _fixes_minor;
+#endif
+
+void
+_ecore_x_fixes_init(void)
+{
+#ifdef ECORE_XFIXES
+   _fixes_major = 3;
+   _fixes_minor = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XFixesQueryVersion(_ecore_x_disp, &_fixes_major, &_fixes_minor))
+     _fixes_available = 1;
+   else
+     _fixes_available = 0;
+#else
+   _fixes_available = 0;
+#endif
+}
+
+#ifdef ECORE_XFIXES
+/* I don't know what to call this function. */
+static XRectangle *
+_ecore_x_rectangle_ecore_to_x(Ecore_X_Rectangle *rects, int num)
+{
+   XRectangle *xrect;
+   int i;
+
+   if (num == 0) return NULL;
+
+   xrect = malloc(sizeof(XRectangle) * num);
+   if (!xrect) return NULL;
+   for (i = 0; i < num; i++)
+     {
+       xrect[i].x = rects[i].x;
+       xrect[i].y = rects[i].y;
+       xrect[i].width = rects[i].width;
+       xrect[i].height = rects[i].height;
+     }
+   return xrect;
+}
+
+static Ecore_X_Rectangle *
+_ecore_x_rectangle_x_to_ecore(XRectangle *xrect, int num)
+{
+   Ecore_X_Rectangle *rects;
+   int i;
+
+   if (num == 0) return NULL;
+   rects = malloc(sizeof(Ecore_X_Rectangle) * num);
+   if (!rects) return NULL;
+   for (i = 0; i < num; i++)
+     {
+       rects[i].x = xrect[i].x;
+       rects[i].y = xrect[i].y;
+       rects[i].width = xrect[i].width;
+       rects[i].height = xrect[i].height;
+     }
+   return rects;
+}
+#endif
+
+EAPI Ecore_X_Region
+ecore_x_region_new(Ecore_X_Rectangle *rects, int num)
+{
+#ifdef ECORE_XFIXES
+   Ecore_X_Region region;
+   XRectangle *xrect;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xrect = _ecore_x_rectangle_ecore_to_x(rects, num);
+   region = XFixesCreateRegion(_ecore_x_disp, xrect, num);
+   free(xrect);
+   return region;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Region
+ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap)
+{
+#ifdef ECORE_XFIXES
+   Ecore_X_Region region;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   region = XFixesCreateRegionFromBitmap(_ecore_x_disp, bitmap);
+   return region;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Region
+ecore_x_region_new_from_window(Ecore_X_Window win, Ecore_X_Region_Type type)
+{
+#ifdef ECORE_XFIXES
+   Ecore_X_Region region;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   region = XFixesCreateRegionFromWindow(_ecore_x_disp, win, type);
+   return region;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Region
+ecore_x_region_new_from_gc(Ecore_X_GC gc)
+{
+#ifdef ECORE_XFIXES
+   Ecore_X_Region region;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   region = XFixesCreateRegionFromGC(_ecore_x_disp, gc);
+   return region;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Region
+ecore_x_region_new_from_picture(Ecore_X_Picture picture)
+{
+#ifdef ECORE_XFIXES
+   Ecore_X_Region region;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   region = XFixesCreateRegionFromPicture(_ecore_x_disp, picture);
+   return region;
+#else
+   return 0;
+#endif
+}
+
+EAPI void
+ecore_x_region_free(Ecore_X_Region region)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesDestroyRegion(_ecore_x_disp, region);
+#endif
+}
+
+EAPI void
+ecore_x_region_set(Ecore_X_Region region, Ecore_X_Rectangle *rects, int num)
+{
+#ifdef ECORE_XFIXES
+   XRectangle *xrect = _ecore_x_rectangle_ecore_to_x(rects, num);
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesSetRegion(_ecore_x_disp, region, xrect, num);
+#endif
+}
+
+EAPI void
+ecore_x_region_copy(Ecore_X_Region dest, Ecore_X_Region source)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesCopyRegion(_ecore_x_disp, dest, source);
+#endif
+}
+
+EAPI void
+ecore_x_region_combine(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesUnionRegion(_ecore_x_disp, dest, source1, source2);
+#endif
+}
+
+EAPI void
+ecore_x_region_intersect(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesIntersectRegion(_ecore_x_disp, dest, source1, source2);
+#endif
+}
+
+EAPI void
+ecore_x_region_subtract(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesSubtractRegion(_ecore_x_disp, dest, source1, source2);
+#endif
+}
+
+EAPI void
+ecore_x_region_invert(Ecore_X_Region dest, Ecore_X_Rectangle *bounds, Ecore_X_Region source)
+{
+#ifdef ECORE_XFIXES
+   XRectangle *xbound;
+   int num = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   while (bounds + num) num++;
+   xbound = _ecore_x_rectangle_ecore_to_x(bounds, num);
+
+   XFixesInvertRegion(_ecore_x_disp, dest, xbound, source);
+#endif
+}
+
+EAPI void
+ecore_x_region_translate(Ecore_X_Region region, int dx, int dy)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesTranslateRegion(_ecore_x_disp, region, dx, dy);
+#endif
+}
+
+EAPI void
+ecore_x_region_extents(Ecore_X_Region dest, Ecore_X_Region source)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesRegionExtents(_ecore_x_disp, dest, source);
+#endif
+}
+
+EAPI Ecore_X_Rectangle *
+ecore_x_region_fetch(Ecore_X_Region region, int *num, Ecore_X_Rectangle *bounds){
+#ifdef ECORE_XFIXES
+   Ecore_X_Rectangle *rects;
+   XRectangle *xrect, xbound;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xrect = XFixesFetchRegionAndBounds(_ecore_x_disp, region, num, &xbound);
+   rects = _ecore_x_rectangle_x_to_ecore(xrect, *num);
+   (*bounds).x = xbound.x;
+   (*bounds).y = xbound.y;
+   (*bounds).width = xbound.width;
+   (*bounds).height = xbound.height;
+   return rects;
+#else
+   return NULL;
+#endif
+}
+
+EAPI void
+ecore_x_region_expand(Ecore_X_Region dest, Ecore_X_Region source, unsigned int left, unsigned int right, unsigned int top, unsigned int bottom)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesExpandRegion(_ecore_x_disp, dest, source, left, right, top, bottom);
+#endif
+}
+
+EAPI void
+ecore_x_region_gc_clip_set(Ecore_X_Region region, Ecore_X_GC gc, int x_origin, int y_origin)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesSetGCClipRegion(_ecore_x_disp, gc, x_origin, y_origin, region);
+#endif
+}
+
+EAPI void
+ecore_x_region_window_shape_set(Ecore_X_Region region, Ecore_X_Window win, Ecore_X_Shape_Type type, int x_offset, int y_offset)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesSetWindowShapeRegion(_ecore_x_disp, win, type, x_offset, y_offset, region);
+#endif
+}
+
+EAPI void
+ecore_x_region_picture_clip_set(Ecore_X_Region region, Ecore_X_Picture picture, int x_origin, int y_origin)
+{
+#ifdef ECORE_XFIXES
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFixesSetPictureClipRegion(_ecore_x_disp, picture, x_origin, y_origin, region);
+#endif
+}
+
diff --git a/src/lib/ecore_x/xlib/ecore_x_gc.c b/src/lib/ecore_x/xlib/ecore_x_gc.c
new file mode 100644 (file)
index 0000000..7f527e7
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+/**
+ * Creates a new default graphics context associated with the given
+ * drawable.
+ * @param  draw Drawable to create graphics context with.  If @c 0 is
+ *              given instead, the default root window is used.
+ * @param value_mask Bitmask values.
+ * @param value_list List of values. The order of values must be the
+ *                   same than the corresponding bitmaks.
+ * @return The new default graphics context.
+ */
+EAPI Ecore_X_GC
+ecore_x_gc_new(Ecore_X_Drawable draw, Ecore_X_GC_Value_Mask value_mask, const unsigned int *value_list)
+{
+   XGCValues gcv;
+   int       mask;
+   int       index;
+   int       i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!draw) draw = DefaultRootWindow(_ecore_x_disp);
+
+   memset(&gcv, 0, sizeof (gcv));
+
+   for (i = 0, index = 0, mask = 1; i <= 22; i++, mask <<= 1)
+     {
+        switch (mask & value_mask)
+          {
+           case ECORE_X_GC_VALUE_MASK_FUNCTION:
+              gcv.function = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_PLANE_MASK:
+              gcv.plane_mask = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_FOREGROUND:
+              gcv.foreground = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_BACKGROUND:
+              gcv.background = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_LINE_WIDTH:
+              gcv.line_width = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_LINE_STYLE:
+              gcv.line_style = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_CAP_STYLE:
+              gcv.cap_style = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_JOIN_STYLE:
+              gcv.join_style = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_FILL_STYLE:
+              gcv.fill_style = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_FILL_RULE:
+              gcv.fill_rule = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_TILE:
+              gcv.tile = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_STIPPLE:
+              gcv.stipple = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_X:
+              gcv.ts_x_origin = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_Y:
+              gcv.ts_y_origin = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_FONT:
+              gcv.font = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_SUBWINDOW_MODE:
+              gcv.subwindow_mode = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_GRAPHICS_EXPOSURES:
+              gcv.graphics_exposures = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_X:
+              gcv.clip_x_origin = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_Y:
+              gcv.clip_y_origin = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_CLIP_MASK:
+              gcv.clip_mask = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_DASH_OFFSET:
+              gcv.dash_offset = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_DASH_LIST:
+              gcv.dashes = value_list[index];
+              index++;
+              break;
+           case ECORE_X_GC_VALUE_MASK_ARC_MODE:
+              gcv.arc_mode = value_list[index];
+              index++;
+              break;
+          }
+     }
+
+   return XCreateGC(_ecore_x_disp, draw, value_mask, &gcv);
+}
+
+/**
+ * Deletes and frees the given graphics context.
+ * @param gc The given graphics context.
+ */
+EAPI void
+ecore_x_gc_free(Ecore_X_GC gc)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFreeGC(_ecore_x_disp, gc);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_icccm.c b/src/lib/ecore_x/xlib/ecore_x_icccm.c
new file mode 100644 (file)
index 0000000..5afaab4
--- /dev/null
@@ -0,0 +1,1114 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * Various ICCCM related functions.
+ *
+ * This is ALL the code involving anything ICCCM related. for both WM and
+ * client.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+
+EAPI void
+ecore_x_icccm_init(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+}
+
+EAPI void
+ecore_x_icccm_state_set(Ecore_X_Window win, Ecore_X_Window_State_Hint state)
+{
+   unsigned long       c[2];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
+      c[0] = WithdrawnState;
+   else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
+      c[0] = NormalState;
+   else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
+      c[0] = IconicState;
+   c[1] = None;
+   XChangeProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
+                  ECORE_X_ATOM_WM_STATE, 32, PropModeReplace,
+                  (unsigned char *)c, 2);
+}
+
+EAPI Ecore_X_Window_State_Hint
+ecore_x_icccm_state_get(Ecore_X_Window win)
+{
+   unsigned char *prop_ret = NULL;
+   Atom           type_ret;
+   unsigned long  bytes_after, num_ret;
+   int            format_ret;
+   Ecore_X_Window_State_Hint hint;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   hint = ECORE_X_WINDOW_STATE_HINT_NONE;
+   XGetWindowProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
+                     0, 0x7fffffff, False, ECORE_X_ATOM_WM_STATE,
+                     &type_ret, &format_ret, &num_ret, &bytes_after,
+                     &prop_ret);
+   if ((prop_ret) && (num_ret == 2))
+     {
+       if (prop_ret[0] == WithdrawnState)
+         hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
+       else if (prop_ret[0] == NormalState)
+         hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+       else if (prop_ret[0] == IconicState)
+         hint = ECORE_X_WINDOW_STATE_HINT_ICONIC;
+     }
+
+   if (prop_ret)
+     XFree(prop_ret);
+   
+   return hint;
+}
+
+EAPI void
+ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time t)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
+                                ECORE_X_EVENT_MASK_NONE,
+                                ECORE_X_ATOM_WM_DELETE_WINDOW,
+                                t, 0, 0, 0);
+}
+
+EAPI void
+ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time t)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
+                                ECORE_X_EVENT_MASK_NONE,
+                                ECORE_X_ATOM_WM_TAKE_FOCUS,
+                                t, 0, 0, 0);
+}
+
+EAPI void
+ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time t)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
+                                ECORE_X_EVENT_MASK_NONE,
+                                ECORE_X_ATOM_WM_SAVE_YOURSELF,
+                                t, 0, 0, 0);
+}
+
+EAPI void
+ecore_x_icccm_move_resize_send(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   XEvent ev;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ev.type = ConfigureNotify;
+   ev.xconfigure.display = _ecore_x_disp;
+   ev.xconfigure.event = win;
+   ev.xconfigure.window = win;
+   ev.xconfigure.x = x;
+   ev.xconfigure.y = y;
+   ev.xconfigure.width = w;
+   ev.xconfigure.height = h;
+   ev.xconfigure.border_width = 0;
+   ev.xconfigure.above = None;
+   ev.xconfigure.override_redirect = False;
+   XSendEvent(_ecore_x_disp, win, False, StructureNotifyMask, &ev);
+}
+
+EAPI void
+ecore_x_icccm_hints_set(Ecore_X_Window win,
+                       int accepts_focus,
+                       Ecore_X_Window_State_Hint initial_state,
+                       Ecore_X_Pixmap icon_pixmap,
+                       Ecore_X_Pixmap icon_mask,
+                       Ecore_X_Window icon_window,
+                       Ecore_X_Window window_group, int is_urgent)
+{
+   XWMHints           *hints;
+
+   hints = XAllocWMHints();
+   if (!hints)
+      return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   hints->flags = InputHint | StateHint;
+   hints->input = accepts_focus;
+   if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
+      hints->initial_state = WithdrawnState;
+   else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
+      hints->initial_state = NormalState;
+   else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
+      hints->initial_state = IconicState;
+   if (icon_pixmap != 0)
+     {
+       hints->icon_pixmap = icon_pixmap;
+       hints->flags |= IconPixmapHint;
+     }
+   if (icon_mask != 0)
+     {
+       hints->icon_mask = icon_mask;
+       hints->flags |= IconMaskHint;
+     }
+   if (icon_window != 0)
+     {
+       hints->icon_window = icon_window;
+       hints->flags |= IconWindowHint;
+     }
+   if (window_group != 0)
+     {
+       hints->window_group = window_group;
+       hints->flags |= WindowGroupHint;
+     }
+   if (is_urgent)
+      hints->flags |= XUrgencyHint;
+   XSetWMHints(_ecore_x_disp, win, hints);
+   XFree(hints);
+}
+
+EAPI int
+ecore_x_icccm_hints_get(Ecore_X_Window win,
+                       int *accepts_focus,
+                       Ecore_X_Window_State_Hint *initial_state,
+                       Ecore_X_Pixmap *icon_pixmap,
+                       Ecore_X_Pixmap *icon_mask,
+                       Ecore_X_Window *icon_window,
+                       Ecore_X_Window *window_group, int *is_urgent)
+{
+   XWMHints *hints;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (accepts_focus)
+      *accepts_focus = 1;
+   if (initial_state)
+      *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+   if (icon_pixmap)
+      *icon_pixmap = 0;
+   if (icon_mask)
+      *icon_mask = 0;
+   if (icon_window)
+      *icon_window = 0;
+   if (window_group)
+      *window_group = 0;
+   if (is_urgent)
+      *is_urgent = 0;
+   hints = XGetWMHints(_ecore_x_disp, win);
+   if (hints)
+     {
+       if ((hints->flags & InputHint) && (accepts_focus))
+         {
+            if (hints->input)
+               *accepts_focus = 1;
+            else
+               *accepts_focus = 0;
+         }
+       if ((hints->flags & StateHint) && (initial_state))
+         {
+            if (hints->initial_state == WithdrawnState)
+               *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
+            else if (hints->initial_state == NormalState)
+               *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
+            else if (hints->initial_state == IconicState)
+               *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
+         }
+       if ((hints->flags & IconPixmapHint) && (icon_pixmap))
+         {
+            *icon_pixmap = hints->icon_pixmap;
+         }
+       if ((hints->flags & IconMaskHint) && (icon_mask))
+         {
+            *icon_mask = hints->icon_mask;
+         }
+       if ((hints->flags & IconWindowHint) && (icon_window))
+         {
+            *icon_window = hints->icon_window;
+         }
+       if ((hints->flags & WindowGroupHint) && (window_group))
+         {
+            *window_group = hints->window_group;
+         }
+       if ((hints->flags & XUrgencyHint) && (is_urgent))
+         {
+            *is_urgent = 1;
+         }
+       XFree(hints);
+       return 1;
+     }
+   return 0;
+}
+
+EAPI void
+ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win,
+                                int request_pos,
+                                Ecore_X_Gravity gravity,
+                                int min_w, int min_h,
+                                int max_w, int max_h,
+                                int base_w, int base_h,
+                                int step_x, int step_y,
+                                double min_aspect, double max_aspect)
+{
+   XSizeHints  hint;
+   long        mask;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
+     {
+       memset(&hint, 0, sizeof(XSizeHints));
+     }
+
+   hint.flags = 0;
+   if (request_pos)
+     {
+       hint.flags |= USPosition;
+     }
+   if (gravity != ECORE_X_GRAVITY_NW)
+     {
+       hint.flags |= PWinGravity;
+       hint.win_gravity = gravity;
+     }
+   if ((min_w > 0) || (min_h > 0))
+     {
+       hint.flags |= PMinSize;
+       hint.min_width = min_w;
+       hint.min_height = min_h;
+     }
+   if ((max_w > 0) || (max_h > 0))
+     {
+       hint.flags |= PMaxSize;
+       hint.max_width = max_w;
+       hint.max_height = max_h;
+     }
+   if ((base_w > 0) || (base_h > 0))
+     {
+       hint.flags |= PBaseSize;
+       hint.base_width = base_w;
+       hint.base_height = base_h;
+     }
+   if ((step_x > 1) || (step_y > 1))
+     {
+       hint.flags |= PResizeInc;
+       hint.width_inc = step_x;
+       hint.height_inc = step_y;
+     }
+   if ((min_aspect > 0.0) || (max_aspect > 0.0))
+     {
+       hint.flags |= PAspect;
+       hint.min_aspect.x = min_aspect * 10000;
+       hint.min_aspect.y = 10000;
+       hint.max_aspect.x = max_aspect * 10000;
+       hint.max_aspect.y = 10000;
+     }
+   XSetWMNormalHints(_ecore_x_disp, win, &hint);
+}
+
+EAPI int
+ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win,
+                                int *request_pos,
+                                Ecore_X_Gravity *gravity,
+                                int *min_w, int *min_h,
+                                int *max_w, int *max_h,
+                                int *base_w, int *base_h,
+                                int *step_x, int *step_y,
+                                double *min_aspect, double *max_aspect)
+{
+   XSizeHints          hint;
+   long                mask;
+
+   int                 minw = 0, minh = 0;
+   int                 maxw = 32767, maxh = 32767;
+   int                 basew = -1, baseh = -1;
+   int                 stepx = -1, stepy = -1;
+   double              mina = 0.0, maxa = 0.0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
+     return 0;
+
+   if ((hint.flags & USPosition) || ((hint.flags & PPosition)))
+     {
+       if (request_pos)
+          *request_pos = 1;
+     }
+   else
+     {
+       if (request_pos)
+          *request_pos = 0;
+     }
+   if (hint.flags & PWinGravity)
+     {
+       if (gravity)
+          *gravity = hint.win_gravity;
+     }
+   else
+     {
+       if (gravity)
+          *gravity = ECORE_X_GRAVITY_NW;
+     }
+   if (hint.flags & PMinSize)
+     {
+       minw = hint.min_width;
+       minh = hint.min_height;
+     }
+   if (hint.flags & PMaxSize)
+     {
+       maxw = hint.max_width;
+       maxh = hint.max_height;
+       if (maxw < minw)
+          maxw = minw;
+       if (maxh < minh)
+          maxh = minh;
+     }
+   if (hint.flags & PBaseSize)
+     {
+       basew = hint.base_width;
+       baseh = hint.base_height;
+       if (basew > minw)
+          minw = basew;
+       if (baseh > minh)
+          minh = baseh;
+     }
+   if (hint.flags & PResizeInc)
+     {
+       stepx = hint.width_inc;
+       stepy = hint.height_inc;
+       if (stepx < 1)
+          stepx = 1;
+       if (stepy < 1)
+          stepy = 1;
+     }
+   if (hint.flags & PAspect)
+     {
+       if (hint.min_aspect.y > 0)
+          mina = ((double)hint.min_aspect.x) / ((double)hint.min_aspect.y);
+       if (hint.max_aspect.y > 0)
+          maxa = ((double)hint.max_aspect.x) / ((double)hint.max_aspect.y);
+     }
+   if (min_w)
+      *min_w = minw;
+   if (min_h)
+      *min_h = minh;
+   if (max_w)
+      *max_w = maxw;
+   if (max_h)
+      *max_h = maxh;
+   if (base_w)
+      *base_w = basew;
+   if (base_h)
+      *base_h = baseh;
+   if (step_x)
+      *step_x = stepx;
+   if (step_y)
+      *step_y = stepy;
+   if (min_aspect)
+      *min_aspect = mina;
+   if (max_aspect)
+      *max_aspect = maxa;
+   return 1;
+}
+
+EAPI void
+ecore_x_icccm_title_set(Ecore_X_Window win, const char *t)
+{
+   char               *list[1];
+   XTextProperty       xprop;
+   int                 ret;
+
+   if (!t) return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xprop.value = NULL;
+#ifdef X_HAVE_UTF8_STRING
+   list[0] = strdup(t);
+   ret =
+      Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, XUTF8StringStyle,
+                                 &xprop);
+#else
+   list[0] = strdup(t);
+   ret =
+      XmbTextListToTextProperty(_ecore_x_disp, list, 1, XStdICCTextStyle,
+                               &xprop);
+#endif
+   if (ret >= Success)
+     {
+       XSetWMName(_ecore_x_disp, win, &xprop);
+       if (xprop.value) XFree(xprop.value);
+     }
+   else
+     {
+       if (XStringListToTextProperty(list, 1, &xprop) >= Success)
+         {
+            XSetWMName(_ecore_x_disp, win, &xprop);
+            if (xprop.value) XFree(xprop.value);
+         }
+     }
+   free(list[0]);
+}
+
+EAPI char *
+ecore_x_icccm_title_get(Ecore_X_Window win)
+{
+   XTextProperty       xprop;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xprop.value = NULL;
+   if (XGetWMName(_ecore_x_disp, win, &xprop) >= Success)
+     {
+       if (xprop.value)
+         {
+            char **list = NULL;
+            char *t = NULL;
+            int num = 0;
+            int ret;
+
+            if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
+              {
+                 t = strdup((char *)xprop.value);
+              }
+            else
+              {
+
+                 /* convert to utf8 */
+#ifdef X_HAVE_UTF8_STRING
+                 ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
+                                                   &list, &num);
+#else
+                 ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
+                                                 &list, &num);
+#endif
+
+                 if ((ret == XLocaleNotSupported) ||
+                     (ret == XNoMemory) || (ret == XConverterNotFound))
+                   {
+                      t = strdup((char *)xprop.value);
+                   }
+                 else if ((ret >= Success) && (num > 0))
+                   {
+                      t = strdup(list[0]);
+                   }
+                 if (list)
+                   XFreeStringList(list);
+              }
+            
+            if (xprop.value) XFree(xprop.value);
+            return t;
+         }
+     }
+   return NULL;
+}
+
+/**
+ * Set protocol atoms explicitly
+ * @param win The Window
+ * @param protos An array of protocol atoms
+ * @param num the number of members of the array
+ */
+EAPI void
+ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win, Ecore_X_Atom *protos, int num)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num > 0)
+     XSetWMProtocols(_ecore_x_disp, win, (Atom *)(protos), num);
+   else
+     XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_PROTOCOLS);
+}
+
+/**
+ * Set or unset a wm protocol property.
+ * @param win The Window
+ * @param protocol The protocol to enable/disable
+ * @param on On/Off
+ */
+EAPI void
+ecore_x_icccm_protocol_set(Ecore_X_Window win,
+                          Ecore_X_WM_Protocol protocol, int on)
+{
+   Atom               *protos = NULL;
+   Atom                proto;
+   int                 protos_count = 0;
+   int                 already_set = 0;
+   int                 i;
+
+   /* Check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+      return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   proto = _ecore_x_atoms_wm_protocols[protocol];
+
+   if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
+     {
+       protos = NULL;
+       protos_count = 0;
+     }
+
+   for (i = 0; i < protos_count; i++)
+     {
+       if (protos[i] == proto)
+         {
+            already_set = 1;
+            break;
+         }
+     }
+
+   if (on)
+     {
+       Atom *new_protos = NULL;
+
+       if (already_set)
+          goto leave;
+       new_protos = malloc((protos_count + 1) * sizeof(Atom));
+       if (!new_protos)
+          goto leave;
+       for (i = 0; i < protos_count; i++)
+          new_protos[i] = protos[i];
+       new_protos[protos_count] = proto;
+       XSetWMProtocols(_ecore_x_disp, win, new_protos, protos_count + 1);
+       free(new_protos);
+     }
+   else
+     {
+       if (!already_set)
+          goto leave;
+       for (i = 0; i < protos_count; i++)
+         {
+            if (protos[i] == proto)
+              {
+                 int                 j;
+
+                 for (j = i + 1; j < protos_count; j++)
+                    protos[j - 1] = protos[j];
+                 if (protos_count > 1)
+                    XSetWMProtocols(_ecore_x_disp, win, protos,
+                                    protos_count - 1);
+                 else
+                    XDeleteProperty(_ecore_x_disp, win,
+                                    ECORE_X_ATOM_WM_PROTOCOLS);
+                 goto leave;
+              }
+         }
+     }
+
+ leave:
+   if (protos)
+     XFree(protos);
+
+}
+
+/**
+ * Determines whether a protocol is set for a window.
+ * @param win The Window
+ * @param protocol The protocol to query
+ * @return 1 if the protocol is set, else 0.
+ */
+EAPI int
+ecore_x_icccm_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol)
+{
+   Atom                proto, *protos = NULL;
+   int                 i, ret = 0, protos_count = 0;
+
+   /* check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+      return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   proto = _ecore_x_atoms_wm_protocols[protocol];
+
+   if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
+      return 0;
+
+   for (i = 0; i < protos_count; i++)
+      if (protos[i] == proto)
+       {
+          ret = 1;
+          break;
+       }
+
+   if (protos) XFree(protos);
+   return ret;
+
+}
+
+/**
+ * Set a window name & class.
+ * @param win The window
+ * @param n The name string
+ * @param c The class string
+ * 
+ * Set a window name * class
+ */
+EAPI void
+ecore_x_icccm_name_class_set(Ecore_X_Window win, const char *n, const char *c)
+{
+   XClassHint         *xch;
+
+   xch = XAllocClassHint();
+   if (!xch)
+      return;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xch->res_name = (char *)n;
+   xch->res_class = (char *)c;
+   XSetClassHint(_ecore_x_disp, win, xch);
+   XFree(xch);
+}
+
+/**
+ * Get a window name & class.
+ * @param win The window
+ * @param n The name string
+ * @param c The class string
+ * 
+ * Get a window name * class
+ */
+EAPI void
+ecore_x_icccm_name_class_get(Ecore_X_Window win, char **n, char **c)
+{
+   XClassHint          xch;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (n) *n = NULL;
+   if (c) *c = NULL;
+   xch.res_name = NULL;
+   xch.res_class = NULL;
+   if (XGetClassHint(_ecore_x_disp, win, &xch))
+     {
+       if (n)
+         {
+            if (xch.res_name) *n = strdup(xch.res_name);
+         }
+       if (c)
+         {
+            if (xch.res_class) *c = strdup(xch.res_class);
+         }
+       XFree(xch.res_name);
+       XFree(xch.res_class);
+     }
+}
+
+/**
+ * Get a window client machine string.
+ * @param win The window
+ * @return The windows client machine string
+ * 
+ * Return the client machine of a window. String must be free'd when done with.
+ */
+EAPI char               *
+ecore_x_icccm_client_machine_get(Ecore_X_Window win)
+{
+   char               *name;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   name = ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_CLIENT_MACHINE);
+   return name;
+}
+
+/**
+ * Sets the WM_COMMAND property for @a win.
+ * 
+ * @param win  The window.
+ * @param argc Number of arguments.
+ * @param argv Arguments.
+ */
+EAPI void
+ecore_x_icccm_command_set(Ecore_X_Window win, int argc, char **argv)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSetCommand(_ecore_x_disp, win, argv, argc);
+}
+
+/**
+ * Get the WM_COMMAND property for @a win.
+ *
+ * Return the command of a window. String must be free'd when done with.
+ *
+ * @param win  The window.
+ * @param argc Number of arguments.
+ * @param argv Arguments.
+ */
+EAPI void
+ecore_x_icccm_command_get(Ecore_X_Window win, int *argc, char ***argv)
+{
+   int i, c;
+   char **v;
+
+   if (argc) *argc = 0;
+   if (argv) *argv = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetCommand(_ecore_x_disp, win, &v, &c))
+     return;
+   if (c < 1)
+     {
+       if (v)
+         XFreeStringList(v);
+               return;
+     }
+
+   if (argc) *argc = c;
+   if (argv)
+     {
+       (*argv) = malloc(c * sizeof(char *));
+       if (!*argv)
+         { 
+            XFreeStringList(v);
+            if (argc) *argc = 0;
+            return;
+         }
+       for (i = 0; i < c; i++)
+         {
+            if (v[i])
+              (*argv)[i] = strdup(v[i]);
+            else
+              (*argv)[i] = strdup("");
+         }
+     }
+   XFreeStringList(v);
+}
+
+/**
+ * Set a window icon name.
+ * @param win The window
+ * @param t The icon name string
+ * 
+ * Set a window icon name
+ */
+EAPI void
+ecore_x_icccm_icon_name_set(Ecore_X_Window win, const char *t)
+{
+   char               *list[1];
+   XTextProperty       xprop;
+   int                 ret;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xprop.value = NULL;
+#ifdef X_HAVE_UTF8_STRING
+   list[0] = strdup(t);
+   ret = Xutf8TextListToTextProperty(_ecore_x_disp, list, 1,
+                                    XUTF8StringStyle, &xprop);
+#else
+   list[0] = strdup(t);
+   ret = XmbTextListToTextProperty(_ecore_x_disp, list, 1,
+                                  XStdICCTextStyle, &xprop);
+#endif
+   if (ret >= Success)
+     {
+       XSetWMIconName(_ecore_x_disp, win, &xprop);
+       if (xprop.value) XFree(xprop.value);
+     }
+   else
+     {
+       if (XStringListToTextProperty(list, 1, &xprop) >= Success)
+         {
+            XSetWMIconName(_ecore_x_disp, win, &xprop);
+            if (xprop.value) XFree(xprop.value);
+         }
+     }
+   free(list[0]);
+}
+
+/**
+ * Get a window icon name.
+ * @param win The window
+ * @return The windows icon name string
+ * 
+ * Return the icon name of a window. String must be free'd when done with.
+ */
+EAPI char               *
+ecore_x_icccm_icon_name_get(Ecore_X_Window win)
+{
+   XTextProperty       xprop;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xprop.value = NULL;
+   if (XGetWMIconName(_ecore_x_disp, win, &xprop) >= Success)
+     {
+       if (xprop.value)
+         {
+            char              **list = NULL;
+            char               *t = NULL;
+            int                 num = 0;
+            int                 ret;
+
+            if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
+              {
+                 t = strdup((char *)xprop.value);
+              }
+            else
+              {
+
+                 /* convert to utf8 */
+#ifdef X_HAVE_UTF8_STRING
+                 ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
+                                                   &list, &num);
+#else
+                 ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
+                                                 &list, &num);
+#endif
+
+                 if ((ret == XLocaleNotSupported) ||
+                     (ret == XNoMemory) || (ret == XConverterNotFound))
+                   {
+                      t = strdup((char *)xprop.value);
+                   }
+                 else if (ret >= Success)
+                   {
+                      if ((num >= 1) && (list))
+                        {
+                           t = strdup(list[0]);
+                        }
+                      if (list)
+                        XFreeStringList(list);
+                   }
+              }
+            
+            if (xprop.value) XFree(xprop.value);
+            return t;
+         }
+     }
+   return NULL;
+}
+
+/**
+ * Add a subwindow to the list of windows that need a different colormap installed.
+ * @param win The toplevel window
+ * @param subwin The subwindow to be added to the colormap windows list
+ */
+EAPI void
+ecore_x_icccm_colormap_window_set(Ecore_X_Window win, Ecore_X_Window subwin)
+{
+   int                 num = 0, i;
+   unsigned char      *old_data = NULL;
+   unsigned char      *data = NULL;
+   Window             *oldset = NULL;
+   Window             *newset = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_property_get(win,
+                                        ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                        XA_WINDOW, 32, &old_data, &num))
+     {
+       newset = calloc(1, sizeof(Window));
+       if (!newset)
+          return;
+       newset[0] = subwin;
+       num = 1;
+       data = (unsigned char *)newset;
+     }
+   else
+     {
+       newset = calloc(num + 1, sizeof(Window));
+       oldset = (Window *) old_data;
+       if (!newset)
+          return;
+       for (i = 0; i < num; ++i)
+         {
+            if (oldset[i] == subwin)
+              {
+                 if (old_data) XFree(old_data);
+                 old_data = NULL;
+                 free(newset);
+                 return;
+              }
+
+            newset[i] = oldset[i];
+         }
+
+       newset[num++] = subwin;
+       if (old_data) XFree(old_data);
+       data = (unsigned char *)newset;
+     }
+
+   ecore_x_window_prop_property_set(win,
+                                   ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                   XA_WINDOW, 32, data, num);
+   free(newset);
+}
+
+/**
+ * Remove a window from the list of colormap windows.
+ * @param win The toplevel window
+ * @param subwin The window to be removed from the colormap window list.
+ */
+EAPI void
+ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, Ecore_X_Window subwin)
+{
+   int                 num = 0, i, j, k = 0;
+   unsigned char      *old_data = NULL;
+   unsigned char      *data = NULL;
+   Window             *oldset = NULL;
+   Window             *newset = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_prop_property_get(win,
+                                        ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                        XA_WINDOW, 32, &old_data, &num))
+      return;
+
+   oldset = (Window *) old_data;
+   for (i = 0; i < num; i++)
+     {
+       if (oldset[i] == subwin)
+         {
+            if (num == 1)
+              {
+                 XDeleteProperty(_ecore_x_disp,
+                                 win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
+                 if (old_data) XFree(old_data);
+                 old_data = NULL;
+                 return;
+              }
+            else
+              {
+                 newset = calloc(num - 1, sizeof(Window));
+                 data = (unsigned char *)newset;
+                 for (j = 0; j < num; ++j)
+                    if (oldset[j] != subwin)
+                       newset[k++] = oldset[j];
+                 ecore_x_window_prop_property_set(win,
+                                                  ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
+                                                  XA_WINDOW, 32, data, k);
+                 if (old_data) XFree(old_data);
+                 old_data = NULL;
+                 free(newset);
+                 return;
+              }
+         }
+     }
+
+   if (old_data) XFree(old_data);
+}
+
+/**
+ * Specify that a window is transient for another top-level window and should be handled accordingly.
+ * @param win the transient window
+ * @param forwin the toplevel window
+ */
+EAPI void
+ecore_x_icccm_transient_for_set(Ecore_X_Window win, Ecore_X_Window forwin)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSetTransientForHint(_ecore_x_disp, win, forwin);
+}
+
+/**
+ * Remove the transient_for setting from a window.
+ * @param The window
+ */
+EAPI void
+ecore_x_icccm_transient_for_unset(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_TRANSIENT_FOR);
+}
+
+/**
+ * Get the window this window is transient for, if any.
+ * @param win The window to check
+ * @return The window ID of the top-level window, or 0 if the property does not exist.
+ */
+EAPI Ecore_X_Window
+ecore_x_icccm_transient_for_get(Ecore_X_Window win)
+{
+   Window              forwin;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XGetTransientForHint(_ecore_x_disp, win, &forwin))
+     return (Ecore_X_Window) forwin;
+   else
+     return 0;
+
+}
+
+/**
+ * Set the window role hint.
+ * @param win The window
+ * @param role The role string
+ */
+EAPI void
+ecore_x_icccm_window_role_set(Ecore_X_Window win, const char *role)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE,
+                                 (char *)role);
+}
+
+/**
+ * Get the window role.
+ * @param win The window
+ * @return The window's role string.
+ */
+EAPI char               *
+ecore_x_icccm_window_role_get(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE);
+}
+
+/**
+ * Set the window's client leader.
+ * @param win The window
+ * @param l The client leader window
+ *
+ * All non-transient top-level windows created by an app other than
+ * the main window must have this property set to the app's main window.
+ */
+EAPI void
+ecore_x_icccm_client_leader_set(Ecore_X_Window win, Ecore_X_Window l)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
+                                 &l, 1);
+}
+
+/**
+ * Get the window's client leader.
+ * @param win The window
+ * @return The window's client leader window, or 0 if unset */
+EAPI Ecore_X_Window
+ecore_x_icccm_client_leader_get(Ecore_X_Window win)
+{
+   Ecore_X_Window      l;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
+                                     &l, 1) > 0)
+     return l;
+   return 0;
+}
+
+EAPI void
+ecore_x_icccm_iconic_request_send(Ecore_X_Window win, Ecore_X_Window root)
+{
+   XEvent xev;
+
+   if (!win) return;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+
+   xev.xclient.type = ClientMessage;
+   xev.xclient.serial = 0;
+   xev.xclient.send_event = True;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.format = 32;
+   xev.xclient.message_type = ECORE_X_ATOM_WM_CHANGE_STATE;
+   xev.xclient.data.l[0] = IconicState;
+
+   XSendEvent(_ecore_x_disp, root, False,
+              SubstructureNotifyMask | SubstructureRedirectMask, &xev);
+}
+
+/* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */
+/*        hints. each should go in their own file/section so we know which */
+/*        is which. also older kde hints too. we should try support as much */
+/*        as makese sense to support */
diff --git a/src/lib/ecore_x/xlib/ecore_x_image.c b/src/lib/ecore_x/xlib/ecore_x_image.c
new file mode 100644 (file)
index 0000000..aaa4ba0
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+#include <X11/extensions/XShm.h>
+#include <X11/Xutil.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <string.h>
+
+static int _ecore_x_image_shm_can = -1;
+static int _ecore_x_image_err = 0;
+
+static void
+_ecore_x_image_error_handler(Display * d __UNUSED__, XErrorEvent * ev __UNUSED__)
+{
+   _ecore_x_image_err = 1;
+}
+
+static void
+_ecore_x_image_shm_check(void)
+{
+   XErrorHandler ph;
+   XShmSegmentInfo shminfo;
+   XImage *xim;
+   
+   if (_ecore_x_image_shm_can != -1) return;
+   
+   XSync(_ecore_x_disp, False);
+   _ecore_x_image_err = 0;
+   
+   xim = XShmCreateImage(_ecore_x_disp, 
+                         DefaultVisual(_ecore_x_disp, 
+                                       DefaultScreen(_ecore_x_disp)), 
+                         DefaultDepth(_ecore_x_disp, 
+                                      DefaultScreen(_ecore_x_disp)),
+                         ZPixmap, NULL, 
+                         &shminfo, 1, 1);
+   if (!xim)
+     {
+        _ecore_x_image_shm_can = 0;
+        return;
+     }
+
+   shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
+                          IPC_CREAT | 0666);
+   if (shminfo.shmid == -1)
+     {
+        XDestroyImage(xim);
+        _ecore_x_image_shm_can = 0;
+        return;
+     }
+   
+   shminfo.readOnly = False;
+   shminfo.shmaddr  = shmat(shminfo.shmid, 0, 0);
+   xim->data = shminfo.shmaddr;
+   
+   if (xim->data == (char *)-1)
+     {
+        XDestroyImage(xim);
+        _ecore_x_image_shm_can = 0;
+        return;
+     }
+   
+   ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
+   XShmAttach(_ecore_x_disp, &shminfo);
+   XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp), 
+                xim, 0, 0, 0xffffffff);
+   XSync(_ecore_x_disp, False);
+   XSetErrorHandler((XErrorHandler)ph);
+   if (_ecore_x_image_err)
+     {
+        XShmDetach(_ecore_x_disp, &shminfo);
+        XDestroyImage(xim);
+        shmdt(shminfo.shmaddr); 
+        shmctl(shminfo.shmid, IPC_RMID, 0);
+        _ecore_x_image_shm_can = 0;
+        return;
+     }
+   
+   XShmDetach(_ecore_x_disp, &shminfo);
+   XDestroyImage(xim);
+   shmdt(shminfo.shmaddr);
+   shmctl(shminfo.shmid, IPC_RMID, 0);
+   
+   _ecore_x_image_shm_can = 1;
+}
+
+struct _Ecore_X_Image
+{
+   XShmSegmentInfo shminfo;
+   Ecore_X_Visual vis;
+   XImage *xim;
+   int depth;
+   int w, h;
+   int bpl, bpp, rows;
+   unsigned char *data;
+   Eina_Bool shm : 1;
+};
+
+EAPI Ecore_X_Image *
+ecore_x_image_new(int w, int h, Ecore_X_Visual vis, int depth)
+{
+   Ecore_X_Image *im;
+   
+   im = calloc(1, sizeof(Ecore_X_Image));
+   if (!im) return NULL;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   im->w = w;
+   im->h = h;
+   im->vis = vis;
+   im->depth = depth;
+   _ecore_x_image_shm_check();
+   im->shm = _ecore_x_image_shm_can;
+   return im;
+}
+
+EAPI void
+ecore_x_image_free(Ecore_X_Image *im)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (im->shm)
+     {
+        if (im->xim)
+          {
+             XShmDetach(_ecore_x_disp, &(im->shminfo));
+             XDestroyImage(im->xim);
+             shmdt(im->shminfo.shmaddr);
+             shmctl(im->shminfo.shmid, IPC_RMID, 0);
+          }
+     }
+   else
+     {
+        if (im->xim)
+         {
+            free(im->xim->data);
+            im->xim->data = NULL;
+            XDestroyImage(im->xim);
+         }
+     }
+   free(im);
+}
+
+static void
+_ecore_x_image_shm_create(Ecore_X_Image *im)
+{
+   im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth,
+                             ZPixmap, NULL, &(im->shminfo), 
+                             im->w, im->h);
+   if (!im->xim) return;
+
+   im->shminfo.shmid = shmget(IPC_PRIVATE, 
+                              im->xim->bytes_per_line * im->xim->height,
+                              IPC_CREAT | 0666);
+   if (im->shminfo.shmid == -1)
+     {
+        XDestroyImage(im->xim);
+        return;
+     }
+   im->shminfo.readOnly = False;
+   im->shminfo.shmaddr  = shmat(im->shminfo.shmid, 0, 0);
+   im->xim->data = im->shminfo.shmaddr;
+   if ((im->xim->data == (char *)-1) ||
+       (im->xim->data == NULL))
+     {
+        shmdt(im->shminfo.shmaddr);
+        shmctl(im->shminfo.shmid, IPC_RMID, 0);
+        XDestroyImage(im->xim);
+        return;
+     } 
+   XShmAttach(_ecore_x_disp, &im->shminfo);
+   
+   im->data = (unsigned char *)im->xim->data;
+
+   im->bpl = im->xim->bytes_per_line;
+   im->rows = im->xim->height;
+   if (im->xim->bits_per_pixel <= 8) im->bpp = 1;
+   else if (im->xim->bits_per_pixel <= 16) im->bpp = 2;
+   else im->bpp = 4;
+}
+
+EAPI Eina_Bool
+ecore_x_image_get(Ecore_X_Image *im, Ecore_X_Drawable draw, 
+                  int x, int y, int sx, int sy, int w, int h)
+{
+   int ret = 1;
+   XErrorHandler ph;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (im->shm)
+     {
+        if (!im->xim) _ecore_x_image_shm_create(im);
+        if (!im->xim) return 0;
+        _ecore_x_image_err = 0;
+        // optimised path
+        ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
+        if ((sx == 0) && (w == im->w))
+          {
+             im->xim->data = (char *)
+               im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp);
+             im->xim->width = w;
+             im->xim->height = h;
+             if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff))
+               ret = 0;
+             ecore_x_sync();
+          }
+        // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it
+        else
+          {
+             Ecore_X_Image *tim;
+             unsigned char *spixels, *sp, *pixels, *p;
+             int bpp, bpl, rows, sbpp, sbpl, srows;
+             int r;
+             
+             tim = ecore_x_image_new(w, h, im->vis, im->depth);
+             if (tim)
+               {
+                  ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
+                  if (ret)
+                    {
+                       spixels = ecore_x_image_data_get(tim, &sbpl, &srows, &sbpp);
+                       pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
+                       if ((pixels) && (spixels))
+                         {
+                            p = pixels + (sy * bpl) + (sx * bpp);
+                            sp = spixels;
+                            for (r = srows; r > 0; r--)
+                              {
+                                 memcpy(p, sp, sbpl);
+                                 p += bpl;
+                                 sp += sbpl;
+                              }
+                         }
+                    }
+                  ecore_x_image_free(tim);
+               }
+          }
+        XSetErrorHandler((XErrorHandler)ph);
+        if (_ecore_x_image_err) ret = 0;
+     }
+   else
+     {
+        printf("currently unimplemented ecore_x_image_get without shm\n");
+        ret = 0;
+     }
+   return ret;
+}
+
+EAPI void
+ecore_x_image_put(Ecore_X_Image *im __UNUSED__, Ecore_X_Drawable draw __UNUSED__, int x __UNUSED__, int y __UNUSED__, int sx __UNUSED__, int sy __UNUSED__, int w __UNUSED__, int h __UNUSED__)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   printf("ecore_x_image_put: unimplemented!\n");
+}
+
+EAPI void *
+ecore_x_image_data_get(Ecore_X_Image *im, int *bpl, int *rows, int *bpp)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!im->xim) _ecore_x_image_shm_create(im);
+   if (!im->xim) return NULL;
+   
+   if (bpl) *bpl = im->bpl;
+   if (rows) *rows = im->rows;
+   if (bpp) *bpp = im->bpp;
+   return im->data;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_mwm.c b/src/lib/ecore_x/xlib/ecore_x_mwm.c
new file mode 100644 (file)
index 0000000..d580da9
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * Various MWM related functions.
+ *
+ * This is ALL the code involving anything MWM related. for both WM and
+ * client.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+#define ECORE_X_MWM_HINTS_FUNCTIONS           (1 << 0)
+#define ECORE_X_MWM_HINTS_DECORATIONS         (1 << 1)
+#define ECORE_X_MWM_HINTS_INPUT_MODE          (1 << 2)
+#define ECORE_X_MWM_HINTS_STATUS              (1 << 3)
+
+typedef struct _mwmhints
+{
+   CARD32              flags;
+   CARD32              functions;
+   CARD32              decorations;
+   INT32               inputmode;
+   CARD32              status;
+}
+MWMHints;
+
+EAPI int
+ecore_x_mwm_hints_get(Ecore_X_Window win,
+                     Ecore_X_MWM_Hint_Func * fhint,
+                     Ecore_X_MWM_Hint_Decor * dhint,
+                     Ecore_X_MWM_Hint_Input * ihint)
+{
+   unsigned char      *p = NULL;
+   MWMHints           *mwmhints = NULL;
+   int                 num;
+   int                 ret;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = 0;
+   if (!ecore_x_window_prop_property_get(win,
+                                        ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                        ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                        32, &p, &num))
+      return 0;
+   mwmhints = (MWMHints *) p;
+   if (mwmhints)
+     {
+       if (num >= 4)
+         {
+            if (dhint)
+              {
+                 if (mwmhints->flags & ECORE_X_MWM_HINTS_DECORATIONS)
+                    *dhint = mwmhints->decorations;
+                 else
+                    *dhint = ECORE_X_MWM_HINT_DECOR_ALL;
+              }
+            if (fhint)
+              {
+                 if (mwmhints->flags & ECORE_X_MWM_HINTS_FUNCTIONS)
+                    *fhint = mwmhints->functions;
+                 else
+                    *fhint = ECORE_X_MWM_HINT_FUNC_ALL;
+              }
+            if (ihint)
+              {
+                 if (mwmhints->flags & ECORE_X_MWM_HINTS_INPUT_MODE)
+                    *ihint = mwmhints->inputmode;
+                 else
+                    *ihint = ECORE_X_MWM_HINT_INPUT_MODELESS;
+              }
+            ret = 1;
+         }
+       free(mwmhints);
+     }
+   return ret;
+}
+
+EAPI void
+ecore_x_mwm_borderless_set(Ecore_X_Window win, int borderless)
+{
+   unsigned int data[5] = {0, 0, 0, 0, 0};
+
+   data[0] = 2; /* just set the decorations hint! */
+   data[2] = !borderless;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_property_set(win, 
+                                   ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                   ECORE_X_ATOM_MOTIF_WM_HINTS,
+                                   32, (void *)data, 5);
+}
+
diff --git a/src/lib/ecore_x/xlib/ecore_x_netwm.c b/src/lib/ecore_x/xlib/ecore_x_netwm.c
new file mode 100644 (file)
index 0000000..363c886
--- /dev/null
@@ -0,0 +1,1624 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
+
+struct _Ecore_X_Startup_Info
+{
+   Ecore_X_Window win;
+
+   int   init;
+
+   int   buffer_size;
+   char *buffer;
+
+   int   length;
+
+   /* These are the sequence info fields */
+   char *id;
+   char *name;
+   int   screen;
+   char *bin;
+   char *icon;
+   int   desktop;
+   int   timestamp;
+   char *description;
+   char *wmclass;
+   int   silent;
+};
+
+static void  _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, Ecore_X_Atom atom, const char *str);
+static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win, Ecore_X_Atom atom);
+#if 0 /* Unused */
+static int _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
+static int _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, char *data);
+#endif
+static void _ecore_x_netwm_startup_info_free(void *data);
+
+/*
+ * Convenience macros
+ */
+#define _ATOM_SET_UTF8_STRING_LIST(win, atom, string, cnt) \
+   XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8, PropModeReplace, \
+                   (unsigned char *)string, cnt)
+
+/*
+ * Local variables
+ */
+
+static Eina_Hash *startup_info = NULL;
+
+EAPI void
+ecore_x_netwm_init(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   startup_info = eina_hash_string_superfast_new(_ecore_x_netwm_startup_info_free);
+}
+
+EAPI void
+ecore_x_netwm_shutdown(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (startup_info)
+     eina_hash_free(startup_info);
+   startup_info = NULL;
+}
+
+/*
+ * WM identification
+ */
+EAPI void
+ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check,
+                         const char *wm_name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
+   ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1);
+   _ecore_x_window_prop_string_utf8_set(check, ECORE_X_ATOM_NET_WM_NAME, wm_name);
+   /* This one isn't mandatory */
+   _ecore_x_window_prop_string_utf8_set(root, ECORE_X_ATOM_NET_WM_NAME, wm_name);
+}
+
+/*
+ * Set supported atoms
+ */
+EAPI void
+ecore_x_netwm_supported_set(Ecore_X_Window root, Ecore_X_Atom *supported, int num)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_atom_set(root, ECORE_X_ATOM_NET_SUPPORTED, supported, num);
+}
+
+EAPI int
+ecore_x_netwm_supported_get(Ecore_X_Window root, Ecore_X_Atom **supported, int *num)
+{
+   int num_ret;
+
+   if (num) *num = 0;
+   if (supported) *supported = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   num_ret = ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED,
+                                              supported);
+   if (num_ret <= 0)
+      return 0;
+
+   if (num) *num = num_ret;
+   return 1;
+}
+
+/*
+ * Desktop configuration and status
+ */
+EAPI void
+ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
+                                 &n_desks, 1);
+}
+
+EAPI void
+ecore_x_netwm_desk_roots_set(Ecore_X_Window root,
+                            Ecore_X_Window *vroots, unsigned int n_desks)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots, n_desks);
+}
+
+EAPI void
+ecore_x_netwm_desk_names_set(Ecore_X_Window root,
+                            const char **names, unsigned int n_desks)
+{
+   char ss[32], *buf;
+   const char *s;
+   unsigned int i;
+   int l, len;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   buf = NULL;
+   len = 0;
+
+   for (i = 0; i < n_desks; i++)
+     {
+       s = (names) ? names[i] : NULL;
+       if (!s)
+         {
+            /* Default to "Desk-<number>" */
+            sprintf(ss, "Desk-%d", i);
+            s = ss;
+         }
+
+       l = strlen(s) + 1;
+       buf = realloc(buf, len + l);
+       memcpy(buf + len, s, l);
+       len += l;
+     }
+
+   _ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len);
+
+   free(buf);
+}
+
+EAPI void
+ecore_x_netwm_desk_size_set(Ecore_X_Window root, unsigned int width,
+                           unsigned int height)
+{
+   unsigned int size[2];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   size[0] = width;
+   size[1] = height;
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size,
+                                 2);
+}
+
+EAPI void
+ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
+                                unsigned int *origins, unsigned int n_desks)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
+                                 origins, 2 * n_desks);
+}
+
+EAPI void
+ecore_x_netwm_desk_layout_set(Ecore_X_Window root, int orientation,
+                             int columns, int rows,
+                             int starting_corner)
+{
+   unsigned int layout[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   layout[0] = orientation;
+   layout[1] = columns;
+   layout[2] = rows;
+   layout[3] = starting_corner;
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT,
+                                 layout, 4);
+}
+
+EAPI void
+ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
+                                unsigned int *areas, unsigned int n_desks)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas,
+                                 4 * n_desks);
+}
+
+EAPI void
+ecore_x_netwm_desk_current_set(Ecore_X_Window root, unsigned int desk)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk,
+                                 1);
+}
+
+EAPI void
+ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, int on)
+{
+   unsigned int val;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   val = (on) ? 1 : 0;
+   ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val,
+                                 1);
+}
+
+/*
+ * Client status
+ */
+
+/* Mapping order */
+EAPI void
+ecore_x_netwm_client_list_set(Ecore_X_Window root,
+                             Ecore_X_Window *p_clients, unsigned int n_clients)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST,
+                                 p_clients, n_clients);
+}
+
+/* Stacking order */
+EAPI void
+ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,
+                                      Ecore_X_Window *p_clients,
+                                      unsigned int n_clients)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
+                                 p_clients, n_clients);
+}
+
+EAPI void
+ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW,
+                                 &win, 1);
+}
+
+EAPI void
+ecore_x_netwm_client_active_request(Ecore_X_Window root, Ecore_X_Window win, int type, Ecore_X_Window current_win)
+{
+   XEvent xev;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+   
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_NET_ACTIVE_WINDOW;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = type;
+   xev.xclient.data.l[1] = CurrentTime;
+   xev.xclient.data.l[2] = current_win;
+   xev.xclient.data.l[3] = 0;
+   xev.xclient.data.l[4] = 0;
+
+   XSendEvent(_ecore_x_disp, root, False, 
+             SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+}
+
+EAPI void
+ecore_x_netwm_name_set(Ecore_X_Window win, const char *name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name);
+}
+
+EAPI int
+ecore_x_netwm_name_get(Ecore_X_Window win, char **name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_WM_NAME);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_startup_id_set(Ecore_X_Window win, const char *id)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id);
+}
+
+EAPI int
+ecore_x_netwm_startup_id_get(Ecore_X_Window win, char **id)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (id)
+     *id = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_STARTUP_ID);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
+                                       name);
+}
+
+EAPI int
+ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(win,
+                                                 ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME,
+                                       name);
+}
+
+EAPI int
+ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(win,
+                                                 ECORE_X_ATOM_NET_WM_ICON_NAME);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_prop_string_utf8_set(win,
+                                       ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
+                                       name);
+}
+
+EAPI int
+ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (name)
+     *name = _ecore_x_window_prop_string_utf8_get(win,
+                                                 ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
+}
+
+EAPI int
+ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk)
+{
+   int ret;
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP,
+                                       &tmp, 1);
+
+   if (desk) *desk = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+/*
+ * _NET_WM_STRUT is deprecated
+ */
+EAPI void
+ecore_x_netwm_strut_set(Ecore_X_Window win, int left, int right,
+                       int top, int bottom)
+{
+   unsigned int strut[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   strut[0] = left;
+   strut[1] = right;
+   strut[2] = top;
+   strut[3] = bottom;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
+}
+
+/*
+ * _NET_WM_STRUT is deprecated
+ */
+EAPI int
+ecore_x_netwm_strut_get(Ecore_X_Window win, int *left, int *right,
+                       int *top, int *bottom)
+{
+   int ret = 0;
+   unsigned int strut[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
+   if (ret != 4)
+     return 0;
+
+   if (left) *left = strut[0];
+   if (right) *right = strut[1];
+   if (top) *top = strut[2];
+   if (bottom) *bottom = strut[3];
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_strut_partial_set(Ecore_X_Window win, int left, int right,
+                               int top, int bottom, int left_start_y, int left_end_y,
+                               int right_start_y, int right_end_y, int top_start_x,
+                               int top_end_x, int bottom_start_x, int bottom_end_x)
+{
+   unsigned int strut[12];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   strut[0] = left;
+   strut[1] = right;
+   strut[2] = top;
+   strut[3] = bottom;
+   strut[4] = left_start_y;
+   strut[5] = left_end_y;
+   strut[6] = right_start_y;
+   strut[7] = right_end_y;
+   strut[8] = top_start_x;
+   strut[9] = top_end_x;
+   strut[10] = bottom_start_x;
+   strut[11] = bottom_end_x;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
+}
+
+EAPI int
+ecore_x_netwm_strut_partial_get(Ecore_X_Window win, int *left, int *right,
+                               int *top, int *bottom, int *left_start_y, int *left_end_y,
+                               int *right_start_y, int *right_end_y, int *top_start_x,
+                               int *top_end_x, int *bottom_start_x, int *bottom_end_x)
+{
+   int ret = 0;
+   unsigned int strut[12];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12);
+   if (ret != 12)
+     return 0;
+
+   if (left) *left = strut[0];
+   if (right) *right = strut[1];
+   if (top) *top = strut[2];
+   if (bottom) *bottom = strut[3];
+   if (left_start_y) *left_start_y = strut[4];
+   if (left_end_y) *left_end_y = strut[5];
+   if (right_start_y) *right_start_y = strut[6];
+   if (right_end_y) *right_end_y = strut[7];
+   if (top_start_x) *top_start_x = strut[8];
+   if (top_end_x) *top_end_x = strut[9];
+   if (bottom_start_x) *bottom_start_x = strut[10];
+   if (bottom_end_x) *bottom_end_x = strut[11];
+   return 1;
+}
+
+EAPI int
+ecore_x_netwm_icons_get(Ecore_X_Window win, Ecore_X_Icon **icon, int *num)
+{
+   unsigned int *data, *p;
+   unsigned int *src;
+   unsigned int len, icons, i;
+   int num_ret;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num) *num = 0;
+   if (icon) *icon = NULL;
+
+   num_ret = ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON,
+                                                &data);
+   if (num_ret <= 0)
+     return 0;
+   if (!data) return 0;
+   if (num_ret < 2)
+     {
+       free(data);
+       return 0;
+     }
+
+   /* Check how many icons there are */
+   icons = 0;
+   p = data;
+   while (p)
+     {
+       len = p[0] * p[1];
+       p += (len + 2);
+       if ((p - data) > num_ret)
+         {
+            free(data);
+            return 0;
+         }
+       icons++;
+
+       if ((p - data) == num_ret)
+         p = NULL;
+     }
+   if (num) *num = icons;
+
+   /* If the user doesn't want the icons, return */
+   if (!icon)
+     {
+       free(data);
+       return 1;
+     }
+
+   /* Allocate memory */
+   *icon = malloc(icons * sizeof(Ecore_X_Icon));
+   if (!(*icon))
+     {
+       free(data);
+       return 0;
+     }
+
+   /* Fetch the icons */
+   p = data;
+   for (i = 0; i < icons; i++)
+     {
+       unsigned int *ps, *pd, *pe;
+       
+       len = p[0] * p[1];
+       ((*icon)[i]).width = p[0];
+       ((*icon)[i]).height = p[1];
+       src = &(p[2]);
+       ((*icon)[i]).data = malloc(len * sizeof(unsigned int));
+       if (!((*icon)[i]).data)
+         {
+            while (i)
+              free(((*icon)[--i]).data);
+            free(*icon);
+            free(data);
+            return 0;
+         }
+
+       pd = ((*icon)[i]).data;
+       ps = src;
+       pe = ps + len;
+       for (; ps < pe; ps++)
+         {
+            unsigned int r, g, b, a;
+            
+            a = (*ps >> 24) & 0xff;
+            r = (((*ps >> 16) & 0xff) * a) / 255;
+            g = (((*ps >>  8) & 0xff) * a) / 255;
+            b = (((*ps      ) & 0xff) * a) / 255;
+            *pd = (a << 24) | (r << 16) | (g << 8) | (b);
+            pd++;
+         }
+       p += (len + 2);
+     }
+
+   free(data);
+
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height)
+{
+   unsigned int geometry[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   geometry[0] = x;
+   geometry[1] = y;
+   geometry[2] = width;
+   geometry[3] = height;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
+}
+
+EAPI int
+ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, int *x, int *y, int *width, int *height)
+{
+   int ret;
+   unsigned int geometry[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4);
+   if (ret != 4)
+     return 0;
+
+   if (x) *x = geometry[0];
+   if (y) *y = geometry[1];
+   if (width) *width = geometry[2];
+   if (height) *height = geometry[3];
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_pid_set(Ecore_X_Window win, int pid)
+{
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   tmp = pid;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID,
+                                 &tmp, 1);
+}
+
+EAPI int
+ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid)
+{
+   int ret;
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID,
+                                       &tmp, 1);
+   if (pid) *pid = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+EAPI void
+ecore_x_netwm_handled_icons_set(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
+                                 NULL, 0);
+}
+
+EAPI int
+ecore_x_netwm_handled_icons_get(Ecore_X_Window win)
+{
+   int ret = 0;
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
+                                       NULL, 0);
+   return ret == 0 ? 1 : 0;
+}
+
+EAPI void
+ecore_x_netwm_user_time_set(Ecore_X_Window win, unsigned int time)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME,
+                                 &time, 1);
+}
+
+EAPI int
+ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *time)
+{
+   int ret;
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME,
+                                       &tmp, 1);
+   if (time) *time = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+Ecore_X_Window_State
+_ecore_x_netwm_state_get(Ecore_X_Atom a)
+{
+   if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
+     return ECORE_X_WINDOW_STATE_MODAL;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
+     return ECORE_X_WINDOW_STATE_STICKY;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
+     return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
+     return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
+     return ECORE_X_WINDOW_STATE_SHADED;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
+     return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
+     return ECORE_X_WINDOW_STATE_SKIP_PAGER;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
+     return ECORE_X_WINDOW_STATE_HIDDEN;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
+     return ECORE_X_WINDOW_STATE_FULLSCREEN;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
+     return ECORE_X_WINDOW_STATE_ABOVE;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
+     return ECORE_X_WINDOW_STATE_BELOW;
+   else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
+     return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
+   else
+     return ECORE_X_WINDOW_STATE_UNKNOWN;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
+{
+   switch(s)
+     {
+      case ECORE_X_WINDOW_STATE_MODAL:
+        return ECORE_X_ATOM_NET_WM_STATE_MODAL;
+      case ECORE_X_WINDOW_STATE_STICKY:
+        return ECORE_X_ATOM_NET_WM_STATE_STICKY;
+      case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
+        return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
+      case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
+        return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
+      case ECORE_X_WINDOW_STATE_SHADED:
+        return ECORE_X_ATOM_NET_WM_STATE_SHADED;
+      case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
+        return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
+      case ECORE_X_WINDOW_STATE_SKIP_PAGER:
+        return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
+      case ECORE_X_WINDOW_STATE_HIDDEN:
+        return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
+      case ECORE_X_WINDOW_STATE_FULLSCREEN:
+        return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
+      case ECORE_X_WINDOW_STATE_ABOVE:
+        return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
+      case ECORE_X_WINDOW_STATE_BELOW:
+        return ECORE_X_ATOM_NET_WM_STATE_BELOW;
+      case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
+        return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
+      default:
+        return 0;
+     }
+}
+
+EAPI void
+ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State *state, unsigned int num)
+{
+   Ecore_X_Atom  *set;
+   unsigned int   i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!num)
+     {
+       ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE);
+       return;
+     }
+
+   set = malloc(num * sizeof(Ecore_X_Atom));
+   if (!set) return;
+
+   for (i = 0; i < num; i++)
+     set[i] = _ecore_x_netwm_state_atom_get(state[i]);
+
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num);
+
+   free(set);
+}
+
+EAPI int
+ecore_x_netwm_window_state_get(Ecore_X_Window win, Ecore_X_Window_State **state, unsigned int *num)
+{
+   int num_ret, i;
+   Ecore_X_Atom *atoms;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num) *num = 0;
+   if (state) *state = NULL;
+
+   num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE,
+                                              &atoms);
+   if (num_ret <= 0)
+      return 0;
+
+   if (state)
+     {
+       *state = malloc(num_ret * sizeof(Ecore_X_Window_State));
+       if (*state)
+         for (i = 0; i < num_ret; ++i)
+           (*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
+
+       if (num) *num = num_ret;
+     }
+
+   free(atoms);
+   return 1;
+}
+
+static Ecore_X_Window_Type
+_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
+{
+   if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
+     return ECORE_X_WINDOW_TYPE_DESKTOP;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
+     return ECORE_X_WINDOW_TYPE_DOCK;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
+     return ECORE_X_WINDOW_TYPE_TOOLBAR;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
+     return ECORE_X_WINDOW_TYPE_MENU;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
+     return ECORE_X_WINDOW_TYPE_UTILITY;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
+     return ECORE_X_WINDOW_TYPE_SPLASH;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
+     return ECORE_X_WINDOW_TYPE_DIALOG;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
+     return ECORE_X_WINDOW_TYPE_NORMAL;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
+     return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU)
+     return ECORE_X_WINDOW_TYPE_POPUP_MENU;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP)
+     return ECORE_X_WINDOW_TYPE_TOOLTIP;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION)
+     return ECORE_X_WINDOW_TYPE_NOTIFICATION;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO)
+     return ECORE_X_WINDOW_TYPE_COMBO;
+   else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND)
+     return ECORE_X_WINDOW_TYPE_DND;
+   else
+     return ECORE_X_WINDOW_TYPE_UNKNOWN;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
+{
+   switch (type)
+     {
+      case ECORE_X_WINDOW_TYPE_DESKTOP:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
+      case ECORE_X_WINDOW_TYPE_DOCK:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
+      case ECORE_X_WINDOW_TYPE_TOOLBAR:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
+      case ECORE_X_WINDOW_TYPE_MENU:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
+      case ECORE_X_WINDOW_TYPE_UTILITY:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
+      case ECORE_X_WINDOW_TYPE_SPLASH:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
+      case ECORE_X_WINDOW_TYPE_DIALOG:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
+      case ECORE_X_WINDOW_TYPE_NORMAL:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
+      case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
+      case ECORE_X_WINDOW_TYPE_POPUP_MENU:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU;
+      case ECORE_X_WINDOW_TYPE_TOOLTIP:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP;
+      case ECORE_X_WINDOW_TYPE_NOTIFICATION:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION;
+      case ECORE_X_WINDOW_TYPE_COMBO:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO;
+      case ECORE_X_WINDOW_TYPE_DND:
+        return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND;
+      default:
+        return 0;
+     }
+}
+
+/*
+ * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
+ * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
+ */
+EAPI void
+ecore_x_netwm_window_type_set(Ecore_X_Window win, Ecore_X_Window_Type type)
+{
+   Ecore_X_Atom atom;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   atom = _ecore_x_netwm_window_type_atom_get(type);
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                               &atom, 1);
+}
+
+/* FIXME: Maybe return 0 on some conditions? */
+EAPI int
+ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type)
+{
+   int num;
+   Ecore_X_Atom *atoms = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL;
+
+   num = ecore_x_window_prop_atom_list_get(win, 
+                                          ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                                          &atoms);
+   if ((type) && (num >= 1) && (atoms))
+     *type = _ecore_x_netwm_window_type_type_get(atoms[0]);
+
+   free(atoms);
+   if (num >= 1) return 1;
+   return 0;
+}
+
+EAPI int
+ecore_x_netwm_window_types_get(Ecore_X_Window win, Ecore_X_Window_Type **types)
+{
+   int num, i;
+   Ecore_X_Atom *atoms = NULL;
+   Ecore_X_Window_Type *atoms2 = NULL;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (types) *types = NULL;
+   num = ecore_x_window_prop_atom_list_get(win,
+                                          ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                                          &atoms);
+   if ((num <= 0) || (!atoms))
+     {
+       if (atoms) free(atoms);
+       return 0;
+     }
+   atoms2 = malloc(num * sizeof(Ecore_X_Window_Type));
+   if (!atoms2) return 0;
+   for (i = 0; i < num; i++)
+     atoms2[i] = _ecore_x_netwm_window_type_type_get(atoms[i]);
+   free(atoms);
+   if (types) *types = atoms2;
+   else free(atoms2);
+   return num;
+}
+
+static Ecore_X_Atom
+_ecore_x_netwm_action_atom_get(Ecore_X_Action action)
+{
+   switch (action)
+     {
+      case ECORE_X_ACTION_MOVE:
+        return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
+      case ECORE_X_ACTION_RESIZE:
+        return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
+      case ECORE_X_ACTION_MINIMIZE:
+        return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
+      case ECORE_X_ACTION_SHADE:
+        return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
+      case ECORE_X_ACTION_STICK:
+        return ECORE_X_ATOM_NET_WM_ACTION_STICK;
+      case ECORE_X_ACTION_MAXIMIZE_HORZ:
+        return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
+      case ECORE_X_ACTION_MAXIMIZE_VERT:
+        return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
+      case ECORE_X_ACTION_FULLSCREEN:
+        return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
+      case ECORE_X_ACTION_CHANGE_DESKTOP:
+        return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
+      case ECORE_X_ACTION_CLOSE:
+        return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
+      case ECORE_X_ACTION_ABOVE:
+        return ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
+      case ECORE_X_ACTION_BELOW:
+        return ECORE_X_ATOM_NET_WM_ACTION_BELOW;
+      default:
+        return 0;
+     }
+}
+
+/* FIXME: Get complete list */
+EAPI int
+ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, Ecore_X_Action action)
+{
+   int num, i, ret = 0;
+   Ecore_X_Atom *atoms, atom;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   num = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
+                                          &atoms);
+   if (num <= 0)
+     return ret;
+
+   atom = _ecore_x_netwm_action_atom_get(action);
+
+   for (i = 0; i < num; ++i)
+     {
+       if (atom == atoms[i])
+         {
+            ret = 1;
+            break;
+         }
+     }
+
+   free(atoms);
+   return ret;
+}
+
+/* FIXME: Set complete list */
+EAPI void
+ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action *action, unsigned int num)
+{
+   Ecore_X_Atom *set;
+   unsigned int i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!num)
+     {
+       ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
+       return;
+     }
+
+   set = malloc(num * sizeof(Ecore_X_Atom));
+   if (!set) return;
+
+   for (i = 0; i < num; i++)
+     set[i] = _ecore_x_netwm_action_atom_get(action[i]);
+
+   ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, set, num);
+
+   free(set);
+}
+
+EAPI int
+ecore_x_netwm_allowed_action_get(Ecore_X_Window win, Ecore_X_Action **action, unsigned int *num)
+{
+   int num_ret, i;
+   Ecore_X_Atom *atoms;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num) *num = 0;
+   if (action) *action = NULL;
+
+   num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
+                                              &atoms);
+   if (num_ret <= 0)
+      return 0;
+
+   if (action)
+     {
+       *action = malloc(num_ret * sizeof(Ecore_X_Action));
+       if (*action)
+         for (i = 0; i < num_ret; ++i)
+           (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
+
+       if (num) *num = num_ret;
+     }
+
+   free(atoms);
+   return 1;
+}
+
+EAPI void
+ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
+                                 &opacity, 1);
+}
+
+EAPI int
+ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity)
+{
+   int ret;
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
+                                       &tmp, 1);
+   if (opacity) *opacity = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+EAPI void
+ecore_x_netwm_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb)
+{
+   unsigned int frames[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   frames[0] = fl;
+   frames[1] = fr;
+   frames[2] = ft;
+   frames[3] = fb;
+   ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
+}
+
+EAPI int
+ecore_x_netwm_frame_size_get(Ecore_X_Window win, int *fl, int *fr, int *ft, int *fb)
+{
+   int ret = 0;
+   unsigned int frames[4];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4);
+   if (ret != 4)
+     return 0;
+
+   if (fl) *fl = frames[0];
+   if (fr) *fr = frames[1];
+   if (ft) *ft = frames[2];
+   if (fb) *fb = frames[3];
+   return 1;
+}
+
+EAPI int
+ecore_x_netwm_sync_counter_get(Ecore_X_Window win, Ecore_X_Sync_Counter *counter)
+{
+   int ret;
+   unsigned int tmp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
+                                       &tmp, 1);
+
+   if (counter) *counter = tmp;
+   return ret == 1 ? 1 : 0;
+}
+
+EAPI void
+ecore_x_netwm_ping_send(Ecore_X_Window win)
+{
+   XEvent xev;
+
+   if (!win) return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_PING;
+   xev.xclient.data.l[1] = _ecore_x_event_last_time;
+   xev.xclient.data.l[2] = win;
+   xev.xclient.data.l[3] = 0;
+   xev.xclient.data.l[4] = 0;
+
+   XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
+}
+
+EAPI void
+ecore_x_netwm_sync_request_send(Ecore_X_Window win, unsigned int serial)
+{
+   XSyncValue value;
+   XEvent xev;
+
+   if (!win) return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncIntToValue(&value, (int)serial);
+
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
+   xev.xclient.data.l[1] = _ecore_x_event_last_time;
+   xev.xclient.data.l[2] = XSyncValueLow32(value);
+   xev.xclient.data.l[3] = XSyncValueHigh32(value);
+   xev.xclient.data.l[4] = 0;
+
+   XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
+}
+
+EAPI void
+ecore_x_netwm_state_request_send(Ecore_X_Window win, Ecore_X_Window root,
+                                Ecore_X_Window_State s1, Ecore_X_Window_State s2, int set)
+{
+   XEvent xev;
+
+   if (!win) return;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+
+   xev.xclient.type = ClientMessage;
+   xev.xclient.serial = 0;
+   xev.xclient.send_event = True;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.format = 32;
+   xev.xclient.message_type = ECORE_X_ATOM_NET_WM_STATE;
+   xev.xclient.data.l[0] = !!set;
+   xev.xclient.data.l[1] = _ecore_x_netwm_state_atom_get(s1);
+   xev.xclient.data.l[2] = _ecore_x_netwm_state_atom_get(s2);
+   /* 1 == normal client, if someone wants to use this
+    * function in a pager, this should be 2 */
+   xev.xclient.data.l[3] = 1;
+   xev.xclient.data.l[4] = 0;
+
+   XSendEvent(_ecore_x_disp, root, False,
+             SubstructureNotifyMask | SubstructureRedirectMask, &xev);
+}
+
+EAPI void
+ecore_x_netwm_desktop_request_send(Ecore_X_Window win, Ecore_X_Window root, unsigned int desktop)
+{
+   XEvent xev;
+
+   if (!win) return;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!root) root = DefaultRootWindow(_ecore_x_disp);
+
+   xev.xclient.type = ClientMessage;
+   xev.xclient.serial = 0;
+   xev.xclient.send_event = True;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.format = 32;
+   xev.xclient.message_type = ECORE_X_ATOM_NET_WM_DESKTOP;
+   xev.xclient.data.l[0] = desktop;
+
+   XSendEvent(_ecore_x_disp, root, False,
+             SubstructureNotifyMask | SubstructureRedirectMask, &xev);
+}
+
+int
+_ecore_x_netwm_startup_info_begin(Ecore_X_Window win __UNUSED__, char *data __UNUSED__)
+{
+#if 0
+   Ecore_X_Startup_Info *info;
+   unsigned char       *exists = 0;
+
+   if (!startup_info) return 0;
+   info = eina_hash_find(startup_info, (void *)win);
+   if (info)
+     {
+        exists = 1;
+       WRN("Already got info for win: 0x%x", win);
+       _ecore_x_netwm_startup_info_free(info);
+     }
+   info = calloc(1, sizeof(Ecore_X_Startup_Info));
+   if (!info) return 0;
+   info->win = win;
+   info->length = 0;
+   info->buffer_size = 161;
+   info->buffer = calloc(info->buffer_size, sizeof(char));
+   if (!info->buffer)
+     {
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+   memcpy(info->buffer, data, 20);
+   info->length += 20;
+   info->buffer[info->length] = 0;
+   if (exists)
+     eina_hash_modify(startup_info, (void *)info->win, info);
+   else
+     eina_hash_add(startup_info, (void *)info->win, info);
+   if (strlen(info->buffer) != 20)
+     {
+       /* We have a '\0' in there, the message is done */
+       _ecore_x_netwm_startup_info_process(info);
+     }
+#endif
+   return 1;
+}
+
+int
+_ecore_x_netwm_startup_info(Ecore_X_Window win __UNUSED__, char *data __UNUSED__)
+{
+#if 0
+   Ecore_X_Startup_Info *info;
+   char *p;
+
+   if (!startup_info) return 0;
+   info = eina_hash_find(startup_info, (void *)win);
+   if (!info) return 0;
+   if ((info->length + 20) > info->buffer_size)
+     {
+       info->buffer_size += 160;
+       info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
+       if (!info->buffer)
+         {
+            eina_hash_del(startup_info, (void *)info->win);
+            _ecore_x_netwm_startup_info_free(info);
+            return 0;
+         }
+     }
+   memcpy(info->buffer + info->length, data, 20);
+   p = info->buffer + info->length;
+   info->length += 20;
+   info->buffer[info->length] = 0;
+   if (strlen(p) != 20)
+     {
+       /* We have a '\0' in there, the message is done */
+       _ecore_x_netwm_startup_info_process(info);
+     }
+#endif
+   return 1;
+}
+
+/*
+ * Set UTF-8 string property
+ */
+static void
+_ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                                    const char *str)
+{
+   XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8,
+                  PropModeReplace, (unsigned char *)str, strlen(str));
+}
+
+/*
+ * Get UTF-8 string property
+ */
+static char *
+_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win, Ecore_X_Atom atom)
+{
+   char *str;
+   unsigned char *prop_ret;
+   Atom type_ret;
+   unsigned long bytes_after, num_ret;
+   int format_ret;
+
+   str = NULL;
+   prop_ret = NULL;
+   XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
+                     ECORE_X_ATOM_UTF8_STRING, &type_ret,
+                     &format_ret, &num_ret, &bytes_after, &prop_ret);
+   if (prop_ret && num_ret > 0 && format_ret == 8)
+     {
+       str = malloc(num_ret + 1);
+       if (str)
+         {
+            memcpy(str, prop_ret, num_ret);
+            str[num_ret] = '\0';
+         }
+     }
+   if (prop_ret)
+      XFree(prop_ret);
+
+   return str;
+}
+
+#if 0 /* Unused */
+/*
+ * Process startup info
+ */
+static int
+_ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
+{
+   Ecore_X_Event_Startup_Sequence *e;
+   int event;
+   char *p;
+
+   p = strchr(info->buffer, ':');
+   if (!p)
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+   *p = 0;
+   if (!strcmp(info->buffer, "new"))
+     {
+       if (info->init)
+         event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
+       else
+         event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
+       info->init = 1;
+     }
+   else if (!strcmp(info->buffer, "change"))
+     {
+       event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
+     }
+   else if (!strcmp(info->buffer, "remove"))
+     event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
+   else
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+
+   p++;
+
+   if (!_ecore_x_netwm_startup_info_parse(info, p))
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+       return 0;
+     }
+
+   if (info->init)
+     {
+       e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
+       if (!e)
+         {
+            eina_hash_del(startup_info, (void *)info->win);
+            _ecore_x_netwm_startup_info_free(info);
+            return 0;
+         }
+       e->win = info->win;
+       ecore_event_add(event, e, NULL, NULL);
+     }
+
+   if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
+     {
+       eina_hash_del(startup_info, (void *)info->win);
+       _ecore_x_netwm_startup_info_free(info);
+     }
+   else
+     {
+       /* Discard buffer */
+       info->length = 0;
+       info->buffer[0] = 0;
+     }
+   return 1;
+}
+
+/*
+ * Parse startup info
+ */
+static int
+_ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, char *data)
+{
+   while (*data)
+     {
+       int in_quot_sing, in_quot_dbl, escaped;
+       char *p, *pp;
+       char *key;
+       char value[1024];
+
+       /* Skip space */
+       while (*data == ' ') data++;
+       /* Get key */
+       key = data;
+       data = strchr(key, '=');
+       if (!data) return 0;
+       *data = 0;
+       data++;
+
+       /* Get value */
+       p = data;
+       pp = value;
+       in_quot_dbl = 0;
+       in_quot_sing = 0;
+       escaped = 0;
+       while (*p)
+         {
+            if ((pp - value) >= 1024) return 0;
+            if (escaped)
+              {
+                 *pp = *p;
+                 pp++;
+                 escaped = 0;
+              }
+            else if (in_quot_sing)
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\'')
+                   in_quot_sing = 0;
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            else if (in_quot_dbl)
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\"')
+                   in_quot_dbl = 0;
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            else
+              {
+                 if (*p == '\\')
+                   escaped = 1;
+                 else if (*p == '\'')
+                   in_quot_sing = 1;
+                 else if (*p == '\"')
+                   in_quot_dbl = 1;
+                 else if (*p == ' ')
+                   {
+                      break;
+                   }
+                 else
+                   {
+                      *pp = *p;
+                      pp++;
+                   }
+              }
+            p++;
+         }
+       if ((in_quot_dbl) || (in_quot_sing)) return 0;
+       data = p;
+       *pp = 0;
+
+       /* Parse info */
+       if (!strcmp(key, "ID"))
+         {
+            if ((info->id) && (strcmp(info->id, value))) return 0;
+            info->id = strdup(value);
+            p = strstr(value, "_TIME");
+            if (p)
+              {
+                 info->timestamp = atoi(p + 5);
+              }
+         }
+       else if (!strcmp(key, "NAME"))
+         {
+            if (info->name) free(info->name);
+            info->name = strdup(value);
+         }
+       else if (!strcmp(key, "SCREEN"))
+         {
+            info->screen = atoi(value);
+         }
+       else if (!strcmp(key, "BIN"))
+         {
+            if (info->bin) free(info->bin);
+            info->bin = strdup(value);
+         }
+       else if (!strcmp(key, "ICON"))
+         {
+            if (info->icon) free(info->icon);
+            info->icon = strdup(value);
+         }
+       else if (!strcmp(key, "DESKTOP"))
+         {
+            info->desktop = atoi(value);
+         }
+       else if (!strcmp(key, "TIMESTAMP"))
+         {
+            if (!info->timestamp)
+              info->timestamp = atoi(value);
+         }
+       else if (!strcmp(key, "DESCRIPTION"))
+         {
+            if (info->description) free(info->description);
+            info->description = strdup(value);
+         }
+       else if (!strcmp(key, "WMCLASS"))
+         {
+            if (info->wmclass) free(info->wmclass);
+            info->wmclass = strdup(value);
+         }
+       else if (!strcmp(key, "SILENT"))
+         {
+            info->silent = atoi(value);
+         }
+       else
+         {
+            ERR("Ecore X Sequence, Unknown: %s=%s", key, value);
+         }
+     }
+   if (!info->id) return 0;
+   return 1;
+}
+#endif
+
+/*
+ * Free startup info struct
+ */
+static void
+_ecore_x_netwm_startup_info_free(void *data)
+{
+   Ecore_X_Startup_Info *info;
+
+   info = data;
+   if (!info) return;
+   if (info->buffer) free(info->buffer);
+   if (info->id) free(info->id);
+   if (info->name) free(info->name);
+   if (info->bin) free(info->bin);
+   if (info->icon) free(info->icon);
+   if (info->description) free(info->description);
+   if (info->wmclass) free(info->wmclass);
+   free(info);
+}
+
+/*
+ * Is screen composited?
+ */
+EAPI int
+ecore_x_screen_is_composited(int screen)
+{
+   Ecore_X_Window win;
+   static Ecore_X_Atom atom = None;
+   char buf[32];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
+   if (atom == None) atom = XInternAtom(_ecore_x_disp, buf, False);
+   if (atom == None) return 0;
+
+   win = XGetSelectionOwner(_ecore_x_disp, atom);
+
+   return win != None;
+}
+
+EAPI void
+ecore_x_screen_is_composited_set(int screen, Ecore_X_Window win)
+{
+   static Ecore_X_Atom atom = None;
+   char buf[32];
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
+   if (atom == None) atom = XInternAtom(_ecore_x_disp, buf, False);
+   if (atom == None) return;
+   XSetSelectionOwner(_ecore_x_disp, atom, win, _ecore_x_event_last_time);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_pixmap.c b/src/lib/ecore_x/xlib/ecore_x_pixmap.c
new file mode 100644 (file)
index 0000000..5c69770
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+/**
+ * @defgroup Ecore_X_Pixmap_Group X Pixmap Functions
+ *
+ * Functions that operate on pixmaps.
+ */
+
+/**
+ * Creates a new pixmap.
+ * @param   win Window used to determine which screen of the display the
+ *              pixmap should be created on.  If 0, the default root window
+ *              is used.
+ * @param   w   Width of the new pixmap.
+ * @param   h   Height of the new pixmap.
+ * @param   dep Depth of the pixmap.  If 0, the default depth of the default
+ *              screen is used.
+ * @return  New pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI Ecore_X_Pixmap
+ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
+   if (dep == 0) dep = DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp));
+   return XCreatePixmap(_ecore_x_disp, win, w, h, dep);
+}
+
+/**
+ * Deletes the reference to the given pixmap.
+ *
+ * If no other clients have a reference to the given pixmap, the server
+ * will destroy it.
+ *
+ * @param   pmap The given pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_free(Ecore_X_Pixmap pmap)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XFreePixmap(_ecore_x_disp, pmap);
+}
+
+/**
+ * Pastes a rectangular area of the given pixmap onto the given drawable.
+ * @param   pmap The given pixmap.
+ * @param   dest The given drawable.
+ * @param   gc   The graphics context which governs which operation will
+ *               be used to paste the area onto the drawable.
+ * @param   sx   The X position of the area on the pixmap.
+ * @param   sy   The Y position of the area on the pixmap.
+ * @param   w    The width of the area.
+ * @param   h    The height of the area.
+ * @param   dx   The X position at which to paste the area on @p dest.
+ * @param   dy   The Y position at which to paste the area on @p dest.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, Ecore_X_Drawable dest, 
+                    Ecore_X_GC gc, int sx, int sy, 
+                    int w, int h, int dx, int dy)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XCopyArea(_ecore_x_disp, pmap, dest, gc, sx, sy, w, h, dx, dy);
+}
+
+/**
+ * Retrieves the size of the given pixmap.
+ * @param   pmap The given pixmap.
+ * @param   x    Pointer to an integer in which to store the X position.
+ * @param   y    Pointer to an integer in which to store the Y position.
+ * @param   w    Pointer to an integer in which to store the width.
+ * @param   h    Pointer to an integer in which to store the height.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI void
+ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (pmap) ecore_x_drawable_geometry_get(pmap, x, y, w, h);
+}
+
+/**
+ * Retrieves the depth of the given pixmap.
+ * @param   pmap The given pixmap.
+ * @return  The depth of the pixmap.
+ * @ingroup Ecore_X_Pixmap_Group
+ */
+EAPI int
+ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_drawable_depth_get(pmap);
+}
+
diff --git a/src/lib/ecore_x/xlib/ecore_x_private.h b/src/lib/ecore_x/xlib/ecore_x_private.h
new file mode 100644 (file)
index 0000000..484a7f2
--- /dev/null
@@ -0,0 +1,308 @@
+#ifndef _ECORE_X_PRIVATE_H
+#define _ECORE_X_PRIVATE_H
+
+#include <sys/param.h>
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+#define XK_MISCELLANY 1
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xresource.h>
+#include <X11/keysymdef.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/shape.h>
+#include <X11/extensions/sync.h>
+#include <X11/extensions/dpms.h>
+#ifdef ECORE_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+#ifdef ECORE_XPRINT
+#include <X11/extensions/Print.h>
+#endif
+#ifdef ECORE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#ifdef ECORE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef ECORE_XSS
+#include <X11/extensions/scrnsaver.h>
+#endif
+#ifdef ECORE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
+#ifdef ECORE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+#ifdef ECORE_XCOMPOSITE
+#include <X11/extensions/Xcomposite.h>
+#endif
+#ifdef ECORE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+#ifdef ECORE_XDPMS
+#include <X11/extensions/dpms.h>
+#endif
+#ifdef ECORE_XKB
+#include <X11/XKBlib.h>
+#endif
+#ifdef ECORE_XI2
+#include <X11/extensions/XInput2.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_X.h"
+#include "Ecore_Input.h"
+
+extern int _ecore_xlib_log_dom;
+#ifdef ECORE_XLIB_DEFAULT_LOG_COLOR
+# undef ECORE_XLIB_DEFAULT_LOG_COLOR
+#endif
+#define ECORE_XLIB_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_xlib_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_xlib_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_ecore_xlib_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_ecore_xlib_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_xlib_log_dom, __VA_ARGS__)
+
+typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern;
+
+struct _Ecore_X_Selection_Intern
+{
+   Ecore_X_Window    win;
+   Ecore_X_Atom      selection;
+   unsigned char     *data;
+   int               length;
+   Time              time;
+};
+
+typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter;
+
+struct _Ecore_X_Selection_Converter
+{
+   Ecore_X_Atom target;
+   int (*convert)(char *target, void *data, int size, 
+                  void **data_ret, int *size_ret);
+   Ecore_X_Selection_Converter *next;
+};
+
+typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser;
+
+struct _Ecore_X_Selection_Parser
+{
+   char     *target;
+   void *(*parse)(const char *target, void *data, int size, int format);
+   Ecore_X_Selection_Parser *next;
+};
+
+typedef struct _Ecore_X_DND_Source 
+{
+   int version;
+   Ecore_X_Window win, dest;
+   
+   enum {
+      ECORE_X_DND_SOURCE_IDLE,
+      ECORE_X_DND_SOURCE_DRAGGING,
+      ECORE_X_DND_SOURCE_DROPPED,
+      ECORE_X_DND_SOURCE_CONVERTING
+   } state;
+
+   struct {
+      short x, y;
+      unsigned short width, height;
+   } rectangle;
+
+   struct {
+      Ecore_X_Window window;
+      int x, y;
+   } prev;
+
+   Time time;
+
+   Ecore_X_Atom action, accepted_action;
+   
+   int will_accept;
+   int suppress;
+
+   int await_status;
+} Ecore_X_DND_Source;
+
+typedef struct _Ecore_X_DND_Target 
+{
+   int version;
+   Ecore_X_Window win, source;
+   
+   enum {
+      ECORE_X_DND_TARGET_IDLE,
+      ECORE_X_DND_TARGET_ENTERED
+   } state;
+
+   struct {
+      int x, y;
+   } pos;
+   
+   Time time;
+
+   Ecore_X_Atom action, accepted_action;
+   
+   int will_accept;
+} Ecore_X_DND_Target;
+
+
+extern int ECORE_X_MODIFIER_SHIFT;
+extern int ECORE_X_MODIFIER_CTRL;
+extern int ECORE_X_MODIFIER_ALT;
+extern int ECORE_X_MODIFIER_WIN;
+
+extern int ECORE_X_LOCK_SCROLL;
+extern int ECORE_X_LOCK_NUM;
+extern int ECORE_X_LOCK_CAPS;
+
+extern Display *_ecore_x_disp;
+extern double   _ecore_x_double_click_time;
+extern Time     _ecore_x_event_last_time;
+extern Window   _ecore_x_event_last_win;
+extern int      _ecore_x_event_last_root_x;
+extern int      _ecore_x_event_last_root_y;
+extern int      _ecore_x_xcursor;
+extern XIC      _ecore_x_ic;
+
+extern Ecore_X_Atom     _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
+
+extern int      _ecore_window_grabs_num;
+extern Window  *_ecore_window_grabs;
+extern int    (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event);
+extern void    *_ecore_window_grab_replay_data;
+
+extern Ecore_X_Window _ecore_x_private_win;
+
+void _ecore_x_error_handler_init(void);
+void _ecore_x_event_handle_any_event(XEvent *xevent);
+void _ecore_x_event_handle_key_press(XEvent *xevent);
+void _ecore_x_event_handle_key_release(XEvent *xevent);
+void _ecore_x_event_handle_button_press(XEvent *xevent);
+void _ecore_x_event_handle_button_release(XEvent *xevent);
+void _ecore_x_event_handle_motion_notify(XEvent *xevent);
+void _ecore_x_event_handle_enter_notify(XEvent *xevent);
+void _ecore_x_event_handle_leave_notify(XEvent *xevent);
+void _ecore_x_event_handle_focus_in(XEvent *xevent);
+void _ecore_x_event_handle_focus_out(XEvent *xevent);
+void _ecore_x_event_handle_keymap_notify(XEvent *xevent);    
+void _ecore_x_event_handle_expose(XEvent *xevent);
+void _ecore_x_event_handle_graphics_expose(XEvent *xevent);
+void _ecore_x_event_handle_visibility_notify(XEvent *xevent);
+void _ecore_x_event_handle_create_notify(XEvent *xevent);
+void _ecore_x_event_handle_destroy_notify(XEvent *xevent);
+void _ecore_x_event_handle_unmap_notify(XEvent *xevent);
+void _ecore_x_event_handle_map_notify(XEvent *xevent);
+void _ecore_x_event_handle_map_request(XEvent *xevent);
+void _ecore_x_event_handle_reparent_notify(XEvent *xevent);
+void _ecore_x_event_handle_configure_notify(XEvent *xevent);
+void _ecore_x_event_handle_configure_request(XEvent *xevent);
+void _ecore_x_event_handle_gravity_notify(XEvent *xevent);
+void _ecore_x_event_handle_resize_request(XEvent *xevent);
+void _ecore_x_event_handle_circulate_notify(XEvent *xevent);
+void _ecore_x_event_handle_circulate_request(XEvent *xevent);
+void _ecore_x_event_handle_property_notify(XEvent *xevent);
+void _ecore_x_event_handle_selection_clear(XEvent *xevent);
+void _ecore_x_event_handle_selection_request(XEvent *xevent);
+void _ecore_x_event_handle_selection_notify(XEvent *xevent);
+void _ecore_x_event_handle_colormap_notify(XEvent *xevent);
+void _ecore_x_event_handle_client_message(XEvent *xevent);
+void _ecore_x_event_handle_mapping_notify(XEvent *xevent);
+void _ecore_x_event_handle_shape_change(XEvent *xevent);
+void _ecore_x_event_handle_screensaver_notify(XEvent *xevent);
+void _ecore_x_event_handle_sync_counter(XEvent *xevent);
+void _ecore_x_event_handle_sync_alarm(XEvent *xevent);
+#ifdef ECORE_XRANDR
+void _ecore_x_event_handle_randr_change(XEvent *xevent);
+void _ecore_x_event_handle_randr_notify(XEvent *xevent);
+#endif
+#ifdef ECORE_XFIXES
+void _ecore_x_event_handle_fixes_selection_notify(XEvent *xevent);
+#endif
+#ifdef ECORE_XDAMAGE
+void _ecore_x_event_handle_damage_notify(XEvent *xevent);
+#endif
+void _ecore_x_event_handle_generic_event(XEvent *xevent);
+
+void  _ecore_x_selection_data_init(void);
+void  _ecore_x_selection_shutdown(void);
+Ecore_X_Atom
+      _ecore_x_selection_target_atom_get(const char *target);
+char *_ecore_x_selection_target_get(Ecore_X_Atom target);
+Ecore_X_Selection_Intern * 
+      _ecore_x_selection_get(Ecore_X_Atom selection);
+int   _ecore_x_selection_set(Window w, const void *data, int len, Ecore_X_Atom selection);
+int   _ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret);
+void *_ecore_x_selection_parse(const char *target, void *data, int size, int format);
+
+void _ecore_x_sync_magic_send(int val, Ecore_X_Window swin);
+void _ecore_x_window_grab_remove(Ecore_X_Window win);
+void _ecore_x_key_grab_remove(Ecore_X_Window win);
+
+/* from dnd */
+void _ecore_x_dnd_init(void);
+Ecore_X_DND_Source *_ecore_x_dnd_source_get(void);
+Ecore_X_DND_Target *_ecore_x_dnd_target_get(void);
+void _ecore_x_dnd_drag(Ecore_X_Window root, int x, int y);
+void _ecore_x_dnd_shutdown(void);
+
+/* from netwm */
+Ecore_X_Window_State _ecore_x_netwm_state_get(Ecore_X_Atom a);
+int                  _ecore_x_netwm_startup_info_begin(Ecore_X_Window win, char *data);
+int                  _ecore_x_netwm_startup_info(Ecore_X_Window win, char *data);
+
+/* Fixes * Damage * Composite * DPMS */
+void _ecore_x_fixes_init(void);
+void _ecore_x_damage_init(void);
+void _ecore_x_composite_init(void);
+void _ecore_x_dpms_init(void);
+void _ecore_x_randr_init(void);
+
+void _ecore_x_atoms_init(void);
+
+extern int _ecore_x_xi2_opcode;
+
+void _ecore_x_input_init(void);
+void _ecore_x_input_shutdown(void);
+void _ecore_x_input_handler(XEvent* xevent);    
+/* from sync */
+
+void _ecore_mouse_move(unsigned int timestamp, unsigned int xmodifiers, int x, int y, int x_root, int y_root, unsigned int event_window, unsigned int window, unsigned int root_win, int same_screen, int dev, double radx, double rady, double pressure, double angle, double mx, double my, double mrx, double mry);
+Ecore_Event_Mouse_Button *_ecore_mouse_button(int event, unsigned int timestamp, unsigned int xmodifiers, unsigned int buttons, int x, int y, int x_root, int y_root, unsigned int event_window, unsigned int window, unsigned int root_win, int same_screen, int dev, double radx, double rady, double pressure, double angle, double mx, double my, double mrx, double mry);
+
+//#define LOGFNS 1
+
+#ifdef LOGFNS
+#define LOGFN(fl, ln, fn) printf("-ECORE-X: %25s: %5i - %s\n", fl, ln, fn);
+#else
+#define LOGFN(fl, ln, fn)
+#endif
+
+#endif
diff --git a/src/lib/ecore_x/xlib/ecore_x_randr.c b/src/lib/ecore_x/xlib/ecore_x_randr.c
new file mode 100644 (file)
index 0000000..185c04f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "ecore_x_private.h"
+
+static int _randr_available = 0;
+#ifdef ECORE_XRANDR
+static int _randr_major, _randr_minor, _randr_version;
+#define RANDR_1_2 ((1 << 16) | 2)
+#define RANDR_1_3 ((1 << 16) | 3)
+#endif
+
+void
+_ecore_x_randr_init(void)
+{
+#ifdef ECORE_XRANDR
+   _randr_major = 1;
+   _randr_minor = 3;
+   _randr_version = 0;
+
+   if (XRRQueryVersion(_ecore_x_disp, &_randr_major, &_randr_minor))
+     {
+       _randr_version = (_randr_major << 16) | _randr_minor;
+       _randr_available = 1;
+     }
+   else
+     _randr_available = 0;
+#else
+   _randr_available = 0;
+#endif
+}
+
+EAPI int
+ecore_x_randr_query(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _randr_available;
+}
+
+EAPI int
+ecore_x_randr_events_select(Ecore_X_Window win, int on)
+{
+#ifdef ECORE_XRANDR
+   int mask;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!on)
+     mask = 0;
+   else
+     {
+       mask = RRScreenChangeNotifyMask;
+       if (_randr_version >= RANDR_1_2)
+         mask |= (RRCrtcChangeNotifyMask |
+                  RROutputChangeNotifyMask |
+                  RROutputPropertyNotifyMask);
+     }
+
+   XRRSelectInput(_ecore_x_disp, win, mask);
+
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Randr_Rotation
+ecore_x_randr_screen_rotations_get(Ecore_X_Window root)
+{
+#ifdef ECORE_XRANDR
+   Rotation rot, crot;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   rot = XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &crot);
+   return rot;
+#else
+   return 0;
+#endif   
+}
+
+EAPI Ecore_X_Randr_Rotation
+ecore_x_randr_screen_rotation_get(Ecore_X_Window root)
+{
+#ifdef ECORE_XRANDR
+   Rotation crot = 0;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &crot);
+   return crot;
+#else
+   return 0;
+#endif   
+}
+
+EAPI void
+ecore_x_randr_screen_rotation_set(Ecore_X_Window root, Ecore_X_Randr_Rotation rot)
+{
+#ifdef ECORE_XRANDR
+   XRRScreenConfiguration *xrrcfg;
+   SizeID sizeid;
+   Rotation crot;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xrrcfg = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (!xrrcfg) return;
+   sizeid = XRRConfigCurrentConfiguration(xrrcfg, &crot);
+   XRRSetScreenConfig(_ecore_x_disp, xrrcfg, root, sizeid, rot, CurrentTime);
+   XRRFreeScreenConfigInfo(xrrcfg);
+#endif   
+}
+
+EAPI Ecore_X_Screen_Size *
+ecore_x_randr_screen_sizes_get(Ecore_X_Window root, int *num)
+{
+#ifdef ECORE_XRANDR
+   Ecore_X_Screen_Size *ret;
+   XRRScreenSize *sizes;
+   int i, n;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num) *num = 0;
+
+   /* we don't have to free sizes, no idea why not */
+   sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
+   ret = calloc(n, sizeof(Ecore_X_Screen_Size));
+   if (!ret) return NULL;
+
+   if (num) *num = n;
+   for (i = 0; i < n; i++)
+     {
+       ret[i].width = sizes[i].width;
+       ret[i].height = sizes[i].height;
+     }
+   return ret;
+#else
+   if (num) *num = 0;
+   return NULL;
+#endif
+}
+
+EAPI Ecore_X_Screen_Size
+ecore_x_randr_current_screen_size_get(Ecore_X_Window root)
+{
+   Ecore_X_Screen_Size ret = { -1, -1 };
+#ifdef ECORE_XRANDR
+   XRRScreenSize *sizes;
+   XRRScreenConfiguration *sc;
+   SizeID size_index;
+   Rotation rotation;
+   int n;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   sc = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (!sc)
+     {
+       ERR("Couldn't get screen information for %d", root);
+       return ret;
+     }
+   size_index = XRRConfigCurrentConfiguration(sc, &rotation);
+
+   sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
+   if (size_index < n)
+     {
+       ret.width = sizes[size_index].width;
+       ret.height = sizes[size_index].height;
+     }
+   XRRFreeScreenConfigInfo(sc);
+#endif
+   return ret;
+}
+
+EAPI int
+ecore_x_randr_screen_size_set(Ecore_X_Window root, Ecore_X_Screen_Size size)
+{
+#ifdef ECORE_XRANDR
+   XRRScreenConfiguration *sc;
+   XRRScreenSize *sizes;
+   int i, n, size_index = -1;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
+   for (i = 0; i < n; i++)
+     {
+       if ((sizes[i].width == size.width) && (sizes[i].height == size.height))
+         {
+            size_index = i;
+            break;
+         }
+     }
+   if (size_index == -1) return 0;
+   
+   sc = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (XRRSetScreenConfig(_ecore_x_disp, sc,
+                         root, size_index,
+                         RR_Rotate_0, CurrentTime))
+     {
+       ERR("Can't set new screen size!");
+       XRRFreeScreenConfigInfo(sc);
+       return 0;
+     }
+   XRRFreeScreenConfigInfo(sc);
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+EAPI Ecore_X_Screen_Refresh_Rate
+ecore_x_randr_current_screen_refresh_rate_get(Ecore_X_Window root)
+{
+   Ecore_X_Screen_Refresh_Rate ret = { -1 };
+#ifdef ECORE_XRANDR
+   XRRScreenConfiguration *sc;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   sc = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (!sc)
+     {
+       ERR("Couldn't get screen information for %d", root);
+       return ret;
+     }
+   ret.rate = XRRConfigCurrentRate(sc);
+   XRRFreeScreenConfigInfo(sc);   
+#endif
+   return ret;
+}
+
+EAPI Ecore_X_Screen_Refresh_Rate *
+ecore_x_randr_screen_refresh_rates_get(Ecore_X_Window root, int size_id, int *num)
+{
+#ifdef ECORE_XRANDR
+   Ecore_X_Screen_Refresh_Rate *ret = NULL;
+   XRRScreenConfiguration *sc;   
+   short *rates;
+   int i, n;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num) *num = 0;
+
+   sc = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (!sc)
+     {
+       ERR("Couldn't get screen information for %d", root);
+       return ret;
+     }
+   
+   rates = XRRRates(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), size_id, &n);
+   ret = calloc(n, sizeof(Ecore_X_Screen_Refresh_Rate));
+   if (!ret) 
+     { 
+       XRRFreeScreenConfigInfo(sc);
+       return NULL;
+     }
+   
+   if (num) *num = n;
+   for (i = 0; i < n; i++)
+     {
+       ret[i].rate = rates[i];
+     }
+   XRRFreeScreenConfigInfo(sc);   
+   return ret;
+#else
+   if (num) *num = 0;   
+   return NULL;
+#endif
+}
+
+EAPI int
+ecore_x_randr_screen_refresh_rate_set(Ecore_X_Window root, Ecore_X_Screen_Size size, Ecore_X_Screen_Refresh_Rate rate)
+{
+#ifdef ECORE_XRANDR
+   XRRScreenConfiguration *sc;
+   XRRScreenSize *sizes;
+   int i, n, size_index = -1;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
+   for (i = 0; i < n; i++)
+     {
+       if ((sizes[i].width == size.width) && (sizes[i].height == size.height))
+         {
+            size_index = i;
+            break;
+         }
+     }
+   if (size_index == -1) return 0;
+   
+   sc = XRRGetScreenInfo(_ecore_x_disp, root);
+   if (XRRSetScreenConfigAndRate(_ecore_x_disp, sc,
+                                root, size_index,
+                                RR_Rotate_0, rate.rate, CurrentTime))
+     {
+       ERR("Can't set new screen size and refresh rate!");
+       XRRFreeScreenConfigInfo(sc);
+       return 0;
+     }
+   XRRFreeScreenConfigInfo(sc);
+   return 1;
+#else
+   return 1;
+#endif
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_region.c b/src/lib/ecore_x/xlib/ecore_x_region.c
new file mode 100644 (file)
index 0000000..eb2345d
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+
+
+/*
+ * [x] XCreateRegion
+ * [ ] XPolygonRegion
+ * [x] XSetRegion
+ * [x] XDestroyRegion
+ *
+ * [x] XOffsetRegion
+ * [ ] XShrinkRegion
+ *
+ * [ ] XClipBox
+ * [x] XIntersectRegion
+ * [x] XUnionRegion
+ * [x] XUnionRectWithRegion
+ * [x] XSubtractRegion
+ * [ ] XXorRegion
+ *
+ * [x] XEmptyRegion
+ * [x] XEqualRegion
+ *
+ * [x] XPointInRegion
+ * [x] XRectInRegion
+ */
+
+EAPI Ecore_X_XRegion *
+ecore_x_xregion_new()
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return (Ecore_X_XRegion *)XCreateRegion();
+}
+
+EAPI void
+ecore_x_xregion_free(Ecore_X_XRegion *region)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!region)
+     return;
+
+   XDestroyRegion((Region)region);
+}
+
+EAPI int
+ecore_x_xregion_set(Ecore_X_XRegion *region, Ecore_X_GC gc)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XSetRegion(_ecore_x_disp, gc, (Region)region);
+}
+
+EAPI void
+ecore_x_xregion_translate(Ecore_X_XRegion *region, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!region)
+     return;
+
+   /* return value not used */
+   XOffsetRegion((Region)region, x, y);
+}
+
+EAPI int
+ecore_x_xregion_intersect(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XIntersectRegion((Region)r1, (Region)r2, (Region)dst);
+}
+
+EAPI int
+ecore_x_xregion_union(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XUnionRegion((Region)r1, (Region)r2, (Region)dst);
+}
+
+EAPI int
+ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, Ecore_X_XRegion *src, Ecore_X_Rectangle *rect)
+{
+   XRectangle xr;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xr.x = rect->x;
+   xr.y = rect->y;
+   xr.width = rect->width;
+   xr.height = rect->height;
+
+   return XUnionRectWithRegion(&xr, (Region)src, (Region)dst);
+}
+
+EAPI int
+ecore_x_xregion_subtract(Ecore_X_XRegion *dst, Ecore_X_XRegion *rm, Ecore_X_XRegion *rs)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XSubtractRegion((Region)rm, (Region)rs, (Region)dst);
+}
+
+EAPI int
+ecore_x_xregion_is_empty(Ecore_X_XRegion *region)
+{
+   if (!region)
+     return 1;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return !XEmptyRegion((Region)region);
+}
+
+EAPI int
+ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, Ecore_X_XRegion *r2)
+{
+   if (!r1 || !r2)
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XEqualRegion((Region)r1, (Region)r1);
+}
+
+EAPI int
+ecore_x_xregion_point_contain(Ecore_X_XRegion *region, int x, int y)
+{
+   if (!region)
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XPointInRegion((Region)region, x, y);
+}
+
+EAPI int
+ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, Ecore_X_Rectangle *rect)
+{
+   if (!region || !rect)
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XRectInRegion((Region)region, rect->x, rect->y, rect->width, rect->height);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_screensaver.c b/src/lib/ecore_x/xlib/ecore_x_screensaver.c
new file mode 100644 (file)
index 0000000..dcb718a
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * Screensaver code
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+static int _screensaver_available = -1;
+
+EAPI int
+ecore_x_screensaver_event_available_get(void)
+{
+   if (_screensaver_available >= 0) return _screensaver_available;
+#ifdef ECORE_XSS
+   int _screensaver_major, _screensaver_minor;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _screensaver_major = 1;
+   _screensaver_minor = 0;
+
+   if (XScreenSaverQueryVersion(_ecore_x_disp, &_screensaver_major, &_screensaver_minor))
+     _screensaver_available = 1;
+   else
+     _screensaver_available = 0;
+#else
+   _screensaver_available = 0;
+#endif
+   return _screensaver_available;
+}
+
+EAPI int
+ecore_x_screensaver_idle_time_get(void)
+{
+#ifdef ECORE_XSS
+   XScreenSaverInfo *xss;
+   int idle;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xss = XScreenSaverAllocInfo();
+   XScreenSaverQueryInfo(_ecore_x_disp, RootWindow(_ecore_x_disp, DefaultScreen(_ecore_x_disp)), xss); 
+   idle = xss->idle / 1000;
+   XFree(xss);
+
+   return idle;
+#endif
+
+   return 0;
+}
+
+EAPI void
+ecore_x_screensaver_set(int timeout, int interval, int prefer_blanking, int allow_exposures)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSetScreenSaver(_ecore_x_disp, timeout, interval, prefer_blanking, allow_exposures);
+}
+
+EAPI void
+ecore_x_screensaver_timeout_set(int timeout)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   XSetScreenSaver(_ecore_x_disp, timeout, pint, pblank, pexpo);
+}
+
+EAPI int
+ecore_x_screensaver_timeout_get(void)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   return pto;
+}
+
+EAPI void
+ecore_x_screensaver_blank_set(int blank)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   XSetScreenSaver(_ecore_x_disp, pto, pint, blank, pexpo);
+}
+
+EAPI int
+ecore_x_screensaver_blank_get(void)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   return pblank;
+}
+
+EAPI void
+ecore_x_screensaver_expose_set(int expose)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   XSetScreenSaver(_ecore_x_disp, pto, pint, pblank, expose);
+}
+
+EAPI int
+ecore_x_screensaver_expose_get(void)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   return pexpo;
+}
+
+EAPI void
+ecore_x_screensaver_interval_set(int interval)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   XSetScreenSaver(_ecore_x_disp, pto, interval, pblank, pexpo);
+}
+
+EAPI int
+ecore_x_screensaver_interval_get(void)
+{
+   int pto, pint, pblank, pexpo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo);
+   return pint;
+}
+
+EAPI void
+ecore_x_screensaver_event_listen_set(int on)
+{
+#ifdef ECORE_XSS
+   Ecore_X_Window root;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   root = DefaultRootWindow(_ecore_x_disp);
+   if (on)
+     XScreenSaverSelectInput(_ecore_x_disp, root, ScreenSaverNotifyMask);
+   else
+     XScreenSaverSelectInput(_ecore_x_disp, root, 0);
+#endif
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_selection.c b/src/lib/ecore_x/xlib/ecore_x_selection.c
new file mode 100644 (file)
index 0000000..3f5ff2e
--- /dev/null
@@ -0,0 +1,834 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+static Ecore_X_Selection_Intern selections[4];
+static Ecore_X_Selection_Converter *converters = NULL;
+static Ecore_X_Selection_Parser *parsers = NULL;
+
+static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
+static int _ecore_x_selection_data_default_free(void *data);
+static void *_ecore_x_selection_parser_files(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_files_free(void *data);
+static void *_ecore_x_selection_parser_text(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_text_free(void *data);
+static void *_ecore_x_selection_parser_targets(const char *target, void *data, int size, int format);
+static int _ecore_x_selection_data_targets_free(void *data);
+
+#define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
+
+void
+_ecore_x_selection_data_init(void)
+{
+   /* Initialize global data */
+   memset(selections, 0, sizeof(selections));
+
+   /* Initialize converters */
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT, 
+                                       _ecore_x_selection_converter_text);
+#ifdef X_HAVE_UTF8_STRING
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING, 
+                                       _ecore_x_selection_converter_text);
+#endif
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
+                                       _ecore_x_selection_converter_text);
+   ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
+                                       _ecore_x_selection_converter_text);
+
+   /* Initialize parsers */
+   ecore_x_selection_parser_add("text/plain",
+                               _ecore_x_selection_parser_text);
+   ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
+                               _ecore_x_selection_parser_text);
+   ecore_x_selection_parser_add("text/uri-list",
+                               _ecore_x_selection_parser_files);
+   ecore_x_selection_parser_add("_NETSCAPE_URL",
+                               _ecore_x_selection_parser_files);
+   ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
+                               _ecore_x_selection_parser_targets);
+}
+
+void
+_ecore_x_selection_shutdown(void)
+{
+   Ecore_X_Selection_Converter *cnv;
+   Ecore_X_Selection_Parser *prs;
+
+   /* free the selection converters */
+   cnv = converters;
+   while (cnv)
+     {
+       Ecore_X_Selection_Converter *tmp;
+
+       tmp = cnv->next;
+       free(cnv);
+       cnv = tmp;
+     }
+   converters = NULL;
+
+   /* free the selection parsers */
+   prs = parsers;
+   while (prs)
+     {
+       Ecore_X_Selection_Parser *tmp;
+
+       tmp = prs;
+       prs = prs->next;
+       free(tmp->target);
+       free(tmp);
+     }
+   parsers = NULL;
+}
+
+Ecore_X_Selection_Intern *
+_ecore_x_selection_get(Ecore_X_Atom selection)
+{
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     return &selections[0];
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     return &selections[1];
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     return &selections[2];
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     return &selections[3];
+   else
+     return NULL;
+}
+
+int 
+_ecore_x_selection_set(Window w, const void *data, int size, Ecore_X_Atom selection)
+{
+   int in;
+   unsigned char *buf = NULL;
+   
+   XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
+   if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
+     return 0;
+   
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     in = 0;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     in = 1;
+   else if (selection == ECORE_X_ATOM_SELECTION_XDND)
+     in = 2;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     in = 3;
+   else
+     return 0;
+
+   if (data)
+     {
+       selections[in].win = w;
+       selections[in].selection = selection;
+       selections[in].length = size;
+       selections[in].time = _ecore_x_event_last_time;
+
+       buf = malloc(size);
+       memcpy(buf, data, size);
+       selections[in].data = buf;
+     }
+   else
+     {
+       if (selections[in].data)
+         {
+            free(selections[in].data);
+            memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
+         }
+     }
+
+   return 1;
+}
+
+/**
+ * Claim ownership of the PRIMARY selection and set its data.
+ * @param w    The window to which this selection belongs
+ * @param data The data associated with the selection
+ * @param size The size of the data buffer in bytes
+ * @return     Returns 1 if the ownership of the selection was successfully 
+ *             claimed, or 0 if unsuccessful.
+ */
+EAPI int 
+ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
+}
+
+/**
+ * Release ownership of the primary selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ */
+EAPI int 
+ecore_x_selection_primary_clear(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
+}
+
+/**
+ * Claim ownership of the SECONDARY selection and set its data.
+ * @param w    The window to which this selection belongs
+ * @param data The data associated with the selection
+ * @param size The size of the data buffer in bytes
+ * @return     Returns 1 if the ownership of the selection was successfully 
+ *             claimed, or 0 if unsuccessful.
+ */
+EAPI int 
+ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_SECONDARY);
+}
+
+/**
+ * Release ownership of the secondary selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ */
+EAPI int 
+ecore_x_selection_secondary_clear(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY);
+}
+
+/**
+ * Claim ownership of the XDND selection and set its data.
+ * @param w    The window to which this selection belongs
+ * @param data The data associated with the selection
+ * @param size The size of the data buffer in bytes
+ * @return     Returns 1 if the ownership of the selection was successfully 
+ *             claimed, or 0 if unsuccessful.
+ */
+EAPI int 
+ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
+}
+
+/**
+ * Release ownership of the XDND selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ */
+EAPI int 
+ecore_x_selection_xdnd_clear(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
+}
+
+/**
+ * Claim ownership of the CLIPBOARD selection and set its data.
+ * @param w    The window to which this selection belongs
+ * @param data The data associated with the selection
+ * @param size The size of the data buffer in bytes
+ * @return     Returns 1 if the ownership of the selection was successfully 
+ *             claimed, or 0 if unsuccessful.
+ *
+ * Get the converted data from a previous CLIPBOARD selection
+ * request. The buffer must be freed when done with.
+ */
+EAPI int 
+ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD);
+}
+
+/**
+ * Release ownership of the clipboard selection
+ * @return     Returns 1 if the selection was successfully cleared,
+ *             or 0 if unsuccessful.
+ *
+ */
+EAPI int 
+ecore_x_selection_clipboard_clear(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD);
+}
+
+Ecore_X_Atom
+_ecore_x_selection_target_atom_get(const char *target)
+{
+   Ecore_X_Atom x_target;
+
+   if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
+     x_target = ECORE_X_ATOM_TEXT;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
+     x_target = ECORE_X_ATOM_COMPOUND_TEXT;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
+     x_target = ECORE_X_ATOM_STRING;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
+     x_target = ECORE_X_ATOM_UTF8_STRING;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
+     x_target = ECORE_X_ATOM_FILE_NAME;
+   else
+     {
+       x_target = ecore_x_atom_get(target);
+     }
+
+   return x_target;
+}
+
+char *
+_ecore_x_selection_target_get(Ecore_X_Atom target)
+{
+   /* FIXME: Should not return mem allocated with strdup or X mixed,
+    * one should use free to free, the other XFree */
+   if (target == ECORE_X_ATOM_FILE_NAME)
+     return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
+   else if (target == ECORE_X_ATOM_STRING)
+     return strdup(ECORE_X_SELECTION_TARGET_STRING);
+   else if (target == ECORE_X_ATOM_UTF8_STRING)
+     return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
+   else if (target == ECORE_X_ATOM_TEXT)
+     return strdup(ECORE_X_SELECTION_TARGET_TEXT);
+   else
+     return XGetAtomName(_ecore_x_disp, target);
+}
+
+static void 
+_ecore_x_selection_request(Ecore_X_Window w, Ecore_X_Atom selection, const char *target_str) 
+{
+   Ecore_X_Atom target, prop;
+
+   target = _ecore_x_selection_target_atom_get(target_str);
+
+   if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
+     prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
+     prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
+   else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
+     prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
+   else
+     return;
+
+   XConvertSelection(_ecore_x_disp, selection, target, prop,
+                    w, CurrentTime);
+}
+
+EAPI void 
+ecore_x_selection_primary_request(Ecore_X_Window w, const char *target)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
+}
+
+EAPI void 
+ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
+}
+
+EAPI void 
+ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target)
+{
+   Ecore_X_Atom atom;
+   Ecore_X_DND_Target *_target;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _target = _ecore_x_dnd_target_get();
+   atom = _ecore_x_selection_target_atom_get(target);
+   XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
+                    ECORE_X_ATOM_SELECTION_PROP_XDND, w,
+                    _target->time);
+}
+
+EAPI void 
+ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
+}
+
+EAPI void
+ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
+      int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
+{
+   Ecore_X_Selection_Converter *cnv;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   cnv = converters;
+   if (converters) 
+     {
+       while (1)
+         {
+            if (cnv->target == target)
+              {
+                 cnv->convert = func;
+                 return;
+              }
+            if (cnv->next)
+              cnv = cnv->next;
+            else
+              break;
+         }
+
+       cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
+       cnv = cnv->next;
+     }
+   else
+     {
+       converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
+       cnv = converters;
+     }
+   cnv->target = target;
+   cnv->convert = func;
+}
+
+EAPI void
+ecore_x_selection_converter_add(char *target, 
+      int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret))
+{
+   Ecore_X_Atom x_target;
+
+   if (!func || !target)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   x_target = _ecore_x_selection_target_atom_get(target);
+
+   ecore_x_selection_converter_atom_add(x_target, func);
+}
+
+EAPI void
+ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
+{
+   Ecore_X_Selection_Converter *cnv, *prev_cnv;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   prev_cnv = NULL;
+   cnv = converters;
+
+   while (cnv)
+     {
+       if (cnv->target == target)
+         {
+            if (prev_cnv)
+              prev_cnv->next = cnv->next;
+            else
+              converters = cnv->next; /* This was the first converter */
+            free(cnv);
+
+            return;
+         }
+       prev_cnv = cnv;
+       cnv = cnv->next;
+     }
+}
+
+EAPI void
+ecore_x_selection_converter_del(char *target)
+{
+   Ecore_X_Atom x_target;
+
+   if (!target)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   x_target = _ecore_x_selection_target_atom_get(target);
+   ecore_x_selection_converter_atom_del(x_target);
+}
+
+EAPI int
+ecore_x_selection_notify_send(Ecore_X_Window requestor, Ecore_X_Atom selection, Ecore_X_Atom target, Ecore_X_Atom property, Ecore_X_Time time)
+{
+   XEvent          xev;
+   XSelectionEvent xnotify;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xnotify.type = SelectionNotify;
+   xnotify.display = _ecore_x_disp;
+   xnotify.requestor = requestor;
+   xnotify.selection = selection;
+   xnotify.target = target;
+   xnotify.property = property;
+   xnotify.time = time;
+   xnotify.send_event = True;
+   xnotify.serial = 0;
+
+   xev.xselection = xnotify;
+   return ((XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? 1 : 0);
+}
+
+/* Locate and run conversion callback for specified selection target */
+EAPI int
+ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret)
+{
+   Ecore_X_Selection_Intern *sel;
+   Ecore_X_Selection_Converter *cnv;
+   void *data;
+   int size;
+   char *tgt_str;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   sel = _ecore_x_selection_get(selection);
+   tgt_str = _ecore_x_selection_target_get(target);
+
+   for (cnv = converters; cnv; cnv = cnv->next)
+     {
+       if (cnv->target == target)
+         {
+            int r;
+            r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
+            free(tgt_str);
+            if (r)
+              {
+                 *data_ret = data;
+                 return r;
+              }
+            else
+              return 0;
+         }
+     }
+
+   /* ICCCM says "If the selection cannot be converted into a form based on the target (and parameters, if any), the owner should refuse the SelectionRequest as previously described." */
+   return 0; 
+
+   /* Default, just return the data 
+   *data_ret = malloc(sel->length);
+   memcpy(*data_ret, sel->data, sel->length);
+   free(tgt_str);
+   return 1;
+   */
+}
+
+/* TODO: We need to work out a mechanism for automatic conversion to any requested
+ * locale using Ecore_Txt functions */
+/* Converter for standard non-utf8 text targets */
+static int
+_ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret)
+{
+   XTextProperty text_prop;
+   char *mystr;
+   XICCEncodingStyle style;
+
+   if (!data || !size)
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
+     style = XTextStyle;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
+     style = XCompoundTextStyle;
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
+     style = XStringStyle;
+#ifdef X_HAVE_UTF8_STRING
+   else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
+     style = XUTF8StringStyle;
+#endif
+   else
+     return 0;
+
+   if (!(mystr = strdup(data)))
+     return 0;
+
+#ifdef X_HAVE_UTF8_STRING
+   if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
+     {
+       int bufsize = strlen((char *)text_prop.value) + 1;
+       *data_ret = malloc(bufsize);
+       memcpy(*data_ret, text_prop.value, bufsize);
+       *size_ret = bufsize;
+       XFree(text_prop.value);
+       free(mystr);
+       return 1;
+     }
+#else
+   if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
+     {
+       int bufsize = strlen(text_prop.value) + 1;
+       *data_ret = malloc(bufsize);
+       memcpy(*data_ret, text_prop.value, bufsize);
+       *size_ret = bufsize;
+       XFree(text_prop.value);
+       free(mystr);
+       return 1;
+     }
+#endif
+   else
+     {
+       free(mystr);
+       return 0;
+     }
+}
+
+EAPI void
+ecore_x_selection_parser_add(const char *target,
+      void *(*func)(const char *target, void *data, int size, int format))
+{
+   Ecore_X_Selection_Parser *prs;
+
+   if (!target)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   prs = parsers;
+   if (parsers) 
+     {
+       while (prs->next)
+         {
+            if (!strcmp(prs->target, target))
+              {
+                 prs->parse = func;
+                 return;
+              }
+            prs = prs->next;
+         }
+
+       prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
+       prs = prs->next;
+     }
+   else
+     {
+       parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
+       prs = parsers;
+     }
+   prs->target = strdup(target);
+   prs->parse = func;
+}
+
+EAPI void
+ecore_x_selection_parser_del(const char *target)
+{
+   Ecore_X_Selection_Parser *prs, *prev_prs;
+
+   if (!target)
+     return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   prev_prs = NULL;
+   prs = parsers;
+
+   while (prs)
+     {
+       if (!strcmp(prs->target, target))
+         {
+            if (prev_prs)
+              prev_prs->next = prs->next;
+            else
+              parsers = prs->next; /* This was the first parser */
+            free(prs->target);
+            free(prs);
+
+            return;
+         }
+       prev_prs = prs;
+       prs = prs->next;
+     }
+}
+
+/* Locate and run conversion callback for specified selection target */
+void *
+_ecore_x_selection_parse(const char *target, void *data, int size, int format)
+{
+   Ecore_X_Selection_Parser *prs;
+   Ecore_X_Selection_Data *sel;
+   
+   for (prs = parsers; prs; prs = prs->next)
+     {
+       if (!strcmp(prs->target, target))
+         {
+            sel = prs->parse(target, data, size, format);
+            return sel;
+         }
+     }
+
+   /* Default, just return the data */
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data));
+   sel->free = _ecore_x_selection_data_default_free;
+   sel->length = size;
+   sel->format = format;
+   sel->data = data;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_default_free(void *data)
+{
+   Ecore_X_Selection_Data *sel;
+
+   sel = data;
+   free(sel->data);
+   free(sel);
+   return 1;
+}
+
+static void *
+_ecore_x_selection_parser_files(const char *target, void *_data, int size, int format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Files *sel;
+   char *data = _data;
+   int i, is;
+   char *tmp;
+
+   if (strcmp(target, "text/uri-list") &&
+       strcmp(target, "_NETSCAPE_URL"))
+     return NULL;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
+
+   if (data[size - 1])
+     {
+       /* Isn't nul terminated */
+       size++;
+       data = realloc(data, size);
+       data[size - 1] = 0;
+     }
+
+   tmp = malloc(size);
+   i = 0;
+   is = 0;
+   while ((is < size) && (data[is]))
+     {
+       if ((i == 0) && (data[is] == '#'))
+         {
+            for (; ((data[is]) && (data[is] != '\n')); is++);
+         }
+       else
+         {
+            if ((data[is] != '\r') &&
+                (data[is] != '\n'))
+              {
+                 tmp[i++] = data[is++];
+              }
+            else
+              {
+                 while ((data[is] == '\r') || (data[is] == '\n')) is++;
+                 tmp[i] = 0;
+                 sel->num_files++;
+                 sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
+                 sel->files[sel->num_files - 1] = strdup(tmp);
+                 tmp[0] = 0;
+                 i = 0;
+              }
+         }
+     }
+   if (i > 0)
+     {
+       tmp[i] = 0;
+       sel->num_files++;
+       sel->files = realloc(sel->files, sel->num_files * sizeof(char *));
+       sel->files[sel->num_files - 1] = strdup(tmp);
+     }
+   free(tmp);
+   free(data);
+
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
+   ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
+
+   return ECORE_X_SELECTION_DATA(sel);
+}
+
+static int
+_ecore_x_selection_data_files_free(void *data)
+{
+   Ecore_X_Selection_Data_Files *sel;
+   int i;
+
+   sel = data;
+   if (sel->files)
+     {
+       for (i = 0; i < sel->num_files; i++)
+         free(sel->files[i]);
+       free(sel->files);
+     }
+   free(sel);
+   return 0;
+}
+
+static void *
+_ecore_x_selection_parser_text(const char *target __UNUSED__, void *_data, int size, int format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Text *sel;
+   char *data = _data;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
+
+   if (data[size - 1])
+     {
+       /* Isn't nul terminated */
+       size++;
+       data = realloc(data, size);
+       data[size - 1] = 0;
+     }
+
+   sel->text = (char *)data;
+   ECORE_X_SELECTION_DATA(sel)->length = size;
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_text_free(void *data)
+{
+   Ecore_X_Selection_Data_Text *sel;
+
+   sel = data;
+   free(sel->text);
+   free(sel);
+   return 1;
+}
+
+static void *
+_ecore_x_selection_parser_targets(const char *target __UNUSED__, void *data, int size, int format __UNUSED__)
+{
+   Ecore_X_Selection_Data_Targets *sel;
+   unsigned long *targets;
+   int i;
+
+   sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
+   targets = (unsigned long *)data;
+
+   sel->num_targets = size - 2;
+   sel->targets = malloc((size - 2) * sizeof(char *));
+   for (i = 2; i < size; i++)
+     sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
+   free(data);
+
+   ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
+   ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
+   ECORE_X_SELECTION_DATA(sel)->length = size;
+   return sel;
+}
+
+static int
+_ecore_x_selection_data_targets_free(void *data)
+{
+   Ecore_X_Selection_Data_Targets *sel;
+   int i;
+
+   sel = data;
+
+   if (sel->targets)
+     {
+       for (i = 0; i < sel->num_targets; i++)
+         XFree(sel->targets[i]);
+       free(sel->targets);
+     }
+   free(sel);
+   return 1;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_sync.c b/src/lib/ecore_x/xlib/ecore_x_sync.c
new file mode 100644 (file)
index 0000000..451ce98
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * XSync code
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+EAPI Ecore_X_Sync_Alarm
+ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter)
+{
+   Ecore_X_Sync_Alarm alarm;
+   XSyncAlarmAttributes values;
+   XSyncValue init;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncIntToValue(&init, 0);
+   XSyncSetCounter(_ecore_x_disp, counter, init);
+   
+   values.trigger.counter = counter;
+   values.trigger.value_type = XSyncAbsolute;
+   XSyncIntToValue(&values.trigger.wait_value, 1);
+   values.trigger.test_type = XSyncPositiveComparison;
+
+   XSyncIntToValue(&values.delta, 1);
+
+   values.events = True;
+
+   alarm = XSyncCreateAlarm(_ecore_x_disp,
+                           XSyncCACounter |
+                           XSyncCAValueType |
+                           XSyncCAValue |
+                           XSyncCATestType |
+                           XSyncCADelta |
+                           XSyncCAEvents,
+                           &values);
+
+   ecore_x_sync();
+   return alarm;
+}
+
+EAPI int
+ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return XSyncDestroyAlarm(_ecore_x_disp, alarm);
+}
+
+EAPI int
+ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, unsigned int *val)
+{
+   XSyncValue value;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (XSyncQueryCounter(_ecore_x_disp, counter, &value))
+     {
+        *val = (unsigned int) XSyncValueLow32(value);
+        return 1;
+     }
+   
+   return 0;
+}
+
+EAPI Ecore_X_Sync_Counter
+ecore_x_sync_counter_new(int val)
+{
+   XSyncCounter counter;
+   XSyncValue v;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncIntToValue(&v, val);
+   counter = XSyncCreateCounter(_ecore_x_disp, v);
+   return counter;
+}
+
+EAPI void
+ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncDestroyCounter(_ecore_x_disp, counter);
+}
+
+EAPI void
+ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, int by)
+{
+   XSyncValue v;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncIntToValue(&v, by);
+   XSyncChangeCounter(_ecore_x_disp, counter, v);
+}
+
+EAPI void
+ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, int val)
+{
+   XSyncWaitCondition cond;
+   XSyncValue v, v2;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSyncQueryCounter(_ecore_x_disp, counter, &v);
+   XSyncIntToValue(&v, val);
+   XSyncIntToValue(&v2, val + 1);
+   cond.trigger.counter = counter;
+   cond.trigger.value_type = XSyncAbsolute;
+   cond.trigger.wait_value = v;
+   cond.trigger.test_type = XSyncPositiveComparison;
+   cond.event_threshold = v2;
+   XSyncAwait(_ecore_x_disp, &cond, 1);
+//   XSync(_ecore_x_disp, False); // dont need this
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_test.c b/src/lib/ecore_x/xlib/ecore_x_test.c
new file mode 100644 (file)
index 0000000..415b6a2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef ECORE_XTEST
+# include <X11/extensions/XTest.h>
+#endif
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include <string.h>
+
+
+EAPI int
+ecore_x_test_fake_key_down(const char *key)
+{
+#ifdef ECORE_XTEST
+   KeyCode             keycode = 0;
+   KeySym              keysym;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   else
+     {
+       keysym = XStringToKeysym(key);
+       if (keysym == NoSymbol) return 0;
+       keycode  = XKeysymToKeycode(_ecore_x_disp, keysym);
+     }
+   if (keycode == 0) return 0;
+   return XTestFakeKeyEvent(_ecore_x_disp, keycode, 1, 0);
+#else
+   return 0;
+#endif
+}
+
+EAPI int
+ecore_x_test_fake_key_up(const char *key)
+{
+#ifdef ECORE_XTEST
+   KeyCode             keycode = 0;
+   KeySym              keysym;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   else
+     {
+       keysym = XStringToKeysym(key);
+       if (keysym == NoSymbol) return 0;
+       keycode  = XKeysymToKeycode(_ecore_x_disp, keysym);
+     }
+   if (keycode == 0) return 0;
+   return XTestFakeKeyEvent(_ecore_x_disp, keycode, 0, 0);
+#else
+   return 0;
+#endif
+}
+
+EAPI int
+ecore_x_test_fake_key_press(const char *key)
+{
+#ifdef ECORE_XTEST
+   KeyCode             keycode = 0;
+   KeySym              keysym = 0;
+   int                 shift = 0;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!strncmp(key, "Keycode-", 8))
+     keycode = atoi(key + 8);
+   else
+     {
+       keysym = XStringToKeysym(key);
+       if (keysym == NoSymbol) return 0;
+       keycode = XKeysymToKeycode(_ecore_x_disp, keysym);
+       if (XKeycodeToKeysym(_ecore_x_disp, keycode, 0) != keysym)
+         {  
+            if (XKeycodeToKeysym(_ecore_x_disp, keycode, 1) == keysym)
+              shift = 1;
+            else
+              keycode = 0;
+         }
+       else
+         shift = 0;
+     }
+   if (keycode == 0)
+     {
+       static int mod = 0;
+       KeySym *keysyms;
+       int keycode_min, keycode_max, keycode_num;
+       int i;  
+
+       XDisplayKeycodes(_ecore_x_disp, &keycode_min, &keycode_max);
+       keysyms = XGetKeyboardMapping(_ecore_x_disp, keycode_min,
+                                     keycode_max - keycode_min + 1,
+                                     &keycode_num);
+       mod = (mod + 1) & 0x7;
+       i = (keycode_max - keycode_min - mod - 1) * keycode_num;
+       
+       keysyms[i] = keysym;
+       XChangeKeyboardMapping(_ecore_x_disp, keycode_min, keycode_num,
+                              keysyms, (keycode_max - keycode_min));
+       XFree(keysyms);
+       XSync(_ecore_x_disp, False);
+       keycode = keycode_max - mod - 1;
+     }
+   if (shift)
+     XTestFakeKeyEvent(_ecore_x_disp, 
+                      XKeysymToKeycode(_ecore_x_disp, XK_Shift_L), 1, 0);
+   XTestFakeKeyEvent(_ecore_x_disp, keycode, 1, 0);
+   XTestFakeKeyEvent(_ecore_x_disp, keycode, 0, 0);
+   if (shift)
+     XTestFakeKeyEvent(_ecore_x_disp, 
+                      XKeysymToKeycode(_ecore_x_disp, XK_Shift_L), 0, 0);
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+EAPI const char *
+ecore_x_keysym_string_get(int keysym)
+{
+   return XKeysymToString(keysym);
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_window.c b/src/lib/ecore_x/xlib/ecore_x_window.c
new file mode 100644 (file)
index 0000000..2067def
--- /dev/null
@@ -0,0 +1,1463 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+static int             ignore_num = 0;
+static Ecore_X_Window *ignore_list = NULL;
+
+/**
+ * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
+ *
+ * Functions that can be used to create an X window.
+ */
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+   Window               win;
+   XSetWindowAttributes attr;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
+   attr.backing_store         = NotUseful;
+   attr.override_redirect     = False;
+   attr.border_pixel          = 0;
+   attr.background_pixmap     = None;
+   attr.bit_gravity            = NorthWestGravity;
+   attr.win_gravity            = NorthWestGravity;
+   attr.save_under            = False;
+   attr.do_not_propagate_mask = NoEventMask;
+   attr.event_mask            = KeyPressMask |
+                                KeyReleaseMask |
+                                ButtonPressMask |
+                                ButtonReleaseMask |
+                                EnterWindowMask |
+                                LeaveWindowMask |
+                                PointerMotionMask |
+                                ExposureMask |
+                                VisibilityChangeMask |
+                                StructureNotifyMask |
+                                FocusChangeMask |
+                                PropertyChangeMask |
+                                ColormapChangeMask;
+   win = XCreateWindow(_ecore_x_disp, parent,
+                      x, y, w, h, 0,
+                      CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
+                      InputOutput, 
+                      CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
+                      CWBackingStore |
+                      CWOverrideRedirect | 
+/*                    CWColormap | */
+                      CWBorderPixel |
+                      CWBackPixmap | 
+                      CWSaveUnder | 
+                      CWDontPropagate | 
+                      CWEventMask |
+                      CWBitGravity |
+                      CWWinGravity,
+                      &attr);
+
+   if (parent == DefaultRootWindow(_ecore_x_disp)) ecore_x_window_defaults_set(win);
+   return win;
+}
+
+/**
+ * Creates a window with the override redirect attribute set to @c True.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+   Window               win;
+   XSetWindowAttributes attr;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
+   attr.backing_store         = NotUseful;
+   attr.override_redirect     = True;
+   attr.border_pixel          = 0;
+   attr.background_pixmap     = None;
+   attr.bit_gravity           = NorthWestGravity;
+   attr.win_gravity           = NorthWestGravity;
+   attr.save_under            = False;
+   attr.do_not_propagate_mask = NoEventMask;
+   attr.event_mask            = KeyPressMask |
+                                KeyReleaseMask |
+                                ButtonPressMask |
+                                ButtonReleaseMask |
+                                EnterWindowMask |
+                                LeaveWindowMask |
+                                PointerMotionMask |
+                                ExposureMask |
+                                VisibilityChangeMask |
+                                StructureNotifyMask |
+                                FocusChangeMask |
+                                PropertyChangeMask |
+                                ColormapChangeMask;
+   win = XCreateWindow(_ecore_x_disp, parent,
+                      x, y, w, h, 0,
+                      CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
+                      InputOutput, 
+                      CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
+                      CWBackingStore |
+                      CWOverrideRedirect | 
+/*                    CWColormap | */
+                      CWBorderPixel |
+                      CWBackPixmap | 
+                      CWSaveUnder | 
+                      CWDontPropagate | 
+                      CWEventMask |
+                      CWBitGravity |
+                      CWWinGravity,
+                      &attr);
+   return win;
+}
+
+/**
+ * Creates a new input window.
+ * @param   parent The parent window to use.    If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_input_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+   Window               win;
+   XSetWindowAttributes attr;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
+   attr.override_redirect     = True;
+   attr.do_not_propagate_mask = NoEventMask;
+   attr.event_mask            = KeyPressMask |
+                                KeyReleaseMask |
+                                ButtonPressMask |
+                                ButtonReleaseMask |
+                                EnterWindowMask |
+                                LeaveWindowMask |
+                                PointerMotionMask |
+                                ExposureMask |
+                                VisibilityChangeMask |
+                                StructureNotifyMask |
+                                FocusChangeMask |
+                                PropertyChangeMask |
+                                ColormapChangeMask;
+   win = XCreateWindow(_ecore_x_disp, parent,
+                      x, y, w, h, 0,
+                      CopyFromParent, 
+                      InputOnly,
+                      CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
+                      CWOverrideRedirect | 
+                      CWDontPropagate | 
+                      CWEventMask,
+                      &attr);
+
+   if (parent == DefaultRootWindow(_ecore_x_disp))
+     {
+     }
+   return win;
+}
+
+/**
+ * @defgroup Ecore_X_Window_Properties_Group X Window Property Functions
+ *
+ * Functions that set window properties.
+ */
+
+/**
+ * Sets the default properties for the given window.
+ *
+ * The default properties set for the window are @c WM_CLIENT_MACHINE and
+ * @c _NET_WM_PID.
+ *
+ * @param   win The given window.
+ * @ingroup Ecore_X_Window_Properties_Groups
+ */
+EAPI void
+ecore_x_window_defaults_set(Ecore_X_Window win)
+{
+   long pid;
+   char buf[MAXHOSTNAMELEN];
+   char *hostname[1];
+   int argc;
+   char **argv;
+   XTextProperty xprop;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /*
+    * Set WM_CLIENT_MACHINE.
+    */
+   gethostname(buf, MAXHOSTNAMELEN);
+   buf[MAXHOSTNAMELEN - 1] = '\0';
+   hostname[0] = buf;
+   /* The ecore function uses UTF8 which Xlib may not like (especially
+    * with older clients) */
+   /* ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
+                                 (char *)buf); */
+   if (XStringListToTextProperty(hostname, 1, &xprop))
+     {
+       XSetWMClientMachine(_ecore_x_disp, win, &xprop);
+       XFree(xprop.value);
+     }
+
+   /*
+    * Set _NET_WM_PID
+    */
+   pid = getpid();
+   ecore_x_netwm_pid_set(win, pid);
+
+   ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL);
+
+   ecore_app_args_get(&argc, &argv);
+   ecore_x_icccm_command_set(win, argc, argv);
+}
+
+EAPI void
+ecore_x_window_configure(Ecore_X_Window win,
+                         Ecore_X_Window_Configure_Mask mask,
+                         int x, int y, int w, int h,
+                         int border_width, Ecore_X_Window sibling,
+                         int stack_mode)
+{
+   XWindowChanges xwc;
+
+   if (!win) return;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   xwc.x = x;
+   xwc.y = y;
+   xwc.width = w;
+   xwc.height = h;
+   xwc.border_width = border_width;
+   xwc.sibling = sibling;
+   xwc.stack_mode = stack_mode;
+
+   XConfigureWindow(_ecore_x_disp, win, mask, &xwc);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions
+ *
+ * Functions to destroy X windows.
+ */
+
+/**
+ * Deletes the given window.
+ * @param   win The given window.
+ * @ingroup Ecore_X_Window_Destroy_Group
+ */
+EAPI void
+ecore_x_window_free(Ecore_X_Window win)
+{
+   /* sorry sir, deleting the root window doesn't sound like
+    * a smart idea.
+    */
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win) XDestroyWindow(_ecore_x_disp, win);
+}
+
+/**
+ * Set if a window should be ignored.
+ * @param   win The given window.
+ * @param   ignore if to ignore
+ */
+EAPI void
+ecore_x_window_ignore_set(Ecore_X_Window win, int ignore)
+{
+   int i, j;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (ignore)
+     {
+       if (ignore_list)
+         {
+            for (i = 0; i < ignore_num; i++)
+              {
+                 if (win == ignore_list[i])
+                   return;
+              }
+            ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
+            if (!ignore_list) return;
+            ignore_list[ignore_num++] = win;
+         }
+       else
+         {
+            ignore_num = 0;
+            ignore_list = malloc(sizeof(Ecore_X_Window));
+            ignore_list[ignore_num++] = win;
+         }
+     }
+   else
+     {
+       if (!ignore_list) return;
+       for (i = 0, j = 0; i < ignore_num; i++)
+         {
+            if (win != ignore_list[i])
+              ignore_list[i] = ignore_list[j++];
+            else
+              ignore_num--;
+         }
+       ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
+     }
+}
+
+/**
+ * Get the ignore list
+ * @param   num number of windows in the list
+ * @return  list of windows to ignore
+ */
+EAPI Ecore_X_Window *
+ecore_x_window_ignore_list(int *num)
+{
+   if (num) *num = ignore_num;
+   return ignore_list;
+}
+
+/**
+ * Sends a delete request to the given window.
+ * @param   win The given window.
+ * @ingroup Ecore_X_Window_Destroy_Group
+ */
+EAPI void
+ecore_x_window_delete_request_send(Ecore_X_Window win)
+{
+   XEvent xev;
+
+   /* sorry sir, deleting the root window doesn't sound like
+    * a smart idea.
+    */
+   if (!win) return;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   xev.xclient.type = ClientMessage;
+   xev.xclient.display = _ecore_x_disp;
+   xev.xclient.window = win;
+   xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
+   xev.xclient.format = 32;
+   xev.xclient.data.l[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
+   xev.xclient.data.l[1] = CurrentTime;
+
+   XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions
+ *
+ * Functions to access and change the visibility of X windows.
+ */
+
+/**
+ * Shows a window.
+ *
+ * Synonymous to "mapping" a window in X Window System terminology.
+ *
+ * @param   win The window to show.
+ * @ingroup Ecore_X_Window_Visibility
+ */
+EAPI void
+ecore_x_window_show(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XMapWindow(_ecore_x_disp, win);
+}
+
+/**
+ * Hides a window.
+ *
+ * Synonymous to "unmapping" a window in X Window System terminology.
+ *
+ * @param   win The window to hide.
+ * @ingroup Ecore_X_Window_Visibility
+ */
+EAPI void
+ecore_x_window_hide(Ecore_X_Window win)
+{
+   XEvent xev;
+   Window root;
+   int idum;
+   unsigned int uidum;
+
+   /* ICCCM: SEND unmap event... */
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   root = win;
+   if (ScreenCount(_ecore_x_disp) == 1)
+     root = DefaultRootWindow(_ecore_x_disp);
+   else
+     XGetGeometry(_ecore_x_disp, win, &root, &idum, &idum, &uidum, &uidum, &uidum, &uidum);
+   xev.xunmap.type = UnmapNotify;
+   xev.xunmap.serial = 0;
+   xev.xunmap.send_event = True;
+   xev.xunmap.display = _ecore_x_disp;
+   xev.xunmap.event = root;
+   xev.xunmap.window = win;
+   xev.xunmap.from_configure = False;
+   XSendEvent(_ecore_x_disp, xev.xunmap.event, False,
+             SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+   XUnmapWindow(_ecore_x_disp, win);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
+ *
+ * Functions that change or retrieve the geometry of X windows.
+ */
+
+/**
+ * Moves a window to the position @p x, @p y.
+ *
+ * The position is relative to the upper left hand corner of the
+ * parent window.
+ *
+ * @param   win The window to move.
+ * @param   x   X position.
+ * @param   y   Y position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_move(Ecore_X_Window win, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XMoveWindow(_ecore_x_disp, win, x, y);
+}
+
+/**
+ * Resizes a window.
+ * @param   win The window to resize.
+ * @param   w   New width of the window.
+ * @param   h   New height of the window.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_resize(Ecore_X_Window win, int w, int h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   XResizeWindow(_ecore_x_disp, win, w, h);
+}
+
+/**
+ * Moves and resizes a window.
+ * @param   win The window to move and resize.
+ * @param   x   New X position of the window.
+ * @param   y   New Y position of the window.
+ * @param   w   New width of the window.
+ * @param   h   New height of the window.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   XMoveResizeWindow(_ecore_x_disp, win, x, y, w, h);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions
+ *
+ * Functions that give the focus to an X Window.
+ */
+
+/**
+ * Sets the focus to the window @p win.
+ * @param   win The window to focus.
+ * @ingroup Ecore_X_Window_Focus_Functions
+ */
+EAPI void
+ecore_x_window_focus(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);   
+//   XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime);
+//   XSetInputFocus(_ecore_x_disp, win, RevertToPointerRoot, CurrentTime);
+   XSetInputFocus(_ecore_x_disp, win, RevertToParent, CurrentTime);
+}
+
+/**
+ * Sets the focus to the given window at a specific time.
+ * @param   win The window to focus.
+ * @param   t   When to set the focus to the window.
+ * @ingroup Ecore_X_Window_Focus_Functions
+ */
+EAPI void
+ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);   
+//   XSetInputFocus(_ecore_x_disp, win, RevertToNone, t);
+//   XSetInputFocus(_ecore_x_disp, win, PointerRoot, t);
+   XSetInputFocus(_ecore_x_disp, win, RevertToParent, t);
+}
+
+/**
+ * gets the focus to the window @p win.
+ * @return  The window that has focus.
+ * @ingroup Ecore_X_Window_Focus_Functions
+ */
+EAPI Ecore_X_Window
+ecore_x_window_focus_get(void)
+{
+   Window win;
+   int revert_mode;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   win = 0;
+   XGetInputFocus(_ecore_x_disp, &win, &revert_mode);
+   return win;
+}
+
+/**
+ * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions
+ *
+ * Functions that change the Z order of X windows.
+ */
+
+/**
+ * Raises the given window.
+ * @param   win The window to raise.
+ * @ingroup Ecore_X_Window_Z_Order_Group
+ */
+EAPI void
+ecore_x_window_raise(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XRaiseWindow(_ecore_x_disp, win);
+}
+
+/**
+ * Lowers the given window.
+ * @param   win The window to lower.
+ * @ingroup Ecore_X_Window_Z_Order_Group
+ */
+EAPI void
+ecore_x_window_lower(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XLowerWindow(_ecore_x_disp, win);
+}
+
+/**
+ * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions
+ *
+ * Functions that retrieve or changes the parent window of a window.
+ */
+
+/**
+ * Moves a window to within another window at a given position.
+ * @param   win        The window to reparent.
+ * @param   new_parent The new parent window.
+ * @param   x          X position within new parent window.
+ * @param   y          Y position within new parent window.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI void
+ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window new_parent, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (new_parent == 0) new_parent = DefaultRootWindow(_ecore_x_disp);   
+   XReparentWindow(_ecore_x_disp, win, new_parent, x, y);
+}
+
+/**
+ * Retrieves the size of the given window.
+ * @param   win The given window.
+ * @param   w   Pointer to an integer into which the width is to be stored.
+ * @param   h   Pointer to an integer into which the height is to be stored.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_size_get(Ecore_X_Window win, int *w, int *h)
+{
+   int dummy_x, dummy_y;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0)  win = DefaultRootWindow(_ecore_x_disp);
+   ecore_x_drawable_geometry_get(win, &dummy_x, &dummy_y, w, h);
+}
+
+/**
+ * Retrieves the geometry of the given window.
+ * @param   win The given window.
+ * @param   x   Pointer to an integer in which the X position is to be stored.
+ * @param   y   Pointer to an integer in which the Y position is to be stored.
+ * @param   w   Pointer to an integer in which the width is to be stored.
+ * @param   h   Pointer to an integer in which the height is to be stored.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!win) win = DefaultRootWindow(_ecore_x_disp);
+   ecore_x_drawable_geometry_get(win, x, y, w, h);
+}
+
+/**
+ * Retrieves the width of the border of the given window.
+ * @param   win The given window.
+ * @return  Width of the border of @p win.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI int
+ecore_x_window_border_width_get(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* doesn't make sense to call this on a root window */
+   if (!win) return 0;
+   return ecore_x_drawable_border_width_get(win);
+}
+
+/**
+ * Sets the width of the border of the given window.
+ * @param   win The given window.
+ * @param   width The new border width.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_border_width_set(Ecore_X_Window win, int width)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* doesn't make sense to call this on a root window */
+   if (!win) return;
+   XSetWindowBorderWidth (_ecore_x_disp, win, width);
+}
+
+/**
+ * Retrieves the depth of the given window.
+ * @param  win The given window.
+ * @return Depth of the window.
+ */
+EAPI int
+ecore_x_window_depth_get(Ecore_X_Window win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_drawable_depth_get(win);
+}
+  
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI void
+ecore_x_window_cursor_show(Ecore_X_Window win, int show)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
+   if (!show)
+     {
+       Cursor              c;
+       XColor              cl;
+       Pixmap              p, m;
+       GC                  gc;
+       XGCValues           gcv;
+       
+       p = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
+       m = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
+       gc = XCreateGC(_ecore_x_disp, m, 0, &gcv);
+       XSetForeground(_ecore_x_disp, gc, 0);
+       XDrawPoint(_ecore_x_disp, m, gc, 0, 0);
+       XFreeGC(_ecore_x_disp, gc);
+       c = XCreatePixmapCursor(_ecore_x_disp, p, m, &cl, &cl, 0, 0);
+       XDefineCursor(_ecore_x_disp, win, c);
+       XFreeCursor(_ecore_x_disp, c);
+       XFreePixmap(_ecore_x_disp, p);
+       XFreePixmap(_ecore_x_disp, m);
+     }
+   else
+     {
+       XDefineCursor(_ecore_x_disp, win, 0);   
+     }
+}
+
+EAPI void
+ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (c == 0)
+     XUndefineCursor(_ecore_x_disp, win);
+   else
+     XDefineCursor(_ecore_x_disp, win, c);
+}
+
+/**
+ * Finds out whether the given window is currently visible.
+ * @param   win The given window.
+ * @return  1 if the window is visible, otherwise 0.
+ * @ingroup Ecore_X_Window_Visibility_Group
+ */
+EAPI int
+ecore_x_window_visible_get(Ecore_X_Window win)
+{
+   XWindowAttributes attr;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return (XGetWindowAttributes(_ecore_x_disp, win, &attr) &&
+           (attr.map_state == IsViewable));
+}
+
+
+
+typedef struct _Shadow Shadow;
+struct _Shadow
+{
+   Shadow         *parent;
+   Shadow        **children;
+   Window          win;
+   int             children_num;
+   short           x, y;
+   unsigned short  w, h;
+};
+
+static Shadow **shadow_base = NULL;
+static int shadow_num = 0;
+
+static Shadow *
+_ecore_x_window_tree_walk(Window win)
+{
+   Window           *list = NULL;
+   Window            parent_win = 0, root_win = 0;
+   unsigned int      num;
+   Shadow           *s, **sl;
+   XWindowAttributes att;
+
+   if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return NULL;
+//   if (att.class == InputOnly) return NULL;
+   if (att.map_state != IsViewable) return NULL;
+   
+   s = calloc(1, sizeof(Shadow));
+   if (!s) return NULL;
+   s->win = win;
+   s->x = att.x;
+   s->y = att.y;
+   s->w = att.width;
+   s->h = att.height;
+   if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win,
+                  &list, &num))
+     {
+       s->children = calloc(1, sizeof(Shadow *) * num);
+       if (s->children)
+         {
+            size_t i, j;
+            s->children_num = num;
+            for (i = 0; i < num; i++)
+              {
+                 s->children[i] = _ecore_x_window_tree_walk(list[i]);
+                 if (s->children[i]) s->children[i]->parent = s;
+              }
+            /* compress list down */
+            j = 0;
+            for (i = 0; i < num; i++)
+              {
+                 if (s->children[i])
+                   {
+                      s->children[j] = s->children[i];
+                      j++;
+                   }
+              }
+            if (j == 0)
+              {
+                 free(s->children);
+                 s->children = NULL;
+                 s->children_num = 0;
+              }
+            else
+              {
+                 s->children_num = j;
+                 sl = realloc(s->children, sizeof(Shadow *) * j);
+                 if (sl) s->children = sl;
+              }
+         }
+     }
+   if (list) XFree(list);
+   return s;
+}
+
+static void
+_ecore_x_window_tree_shadow_free1(Shadow *s)
+{
+   int i;
+
+   if (!s) return;
+   if (s->children)
+     {
+       for (i = 0; i < s->children_num; i++)
+         {
+            if (s->children[i])
+              _ecore_x_window_tree_shadow_free1(s->children[i]);
+         }
+       free(s->children);
+     }
+   free(s);
+}
+
+static void
+_ecore_x_window_tree_shadow_free(void)
+{
+   int i;
+   
+   if (!shadow_base) return;
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       _ecore_x_window_tree_shadow_free1(shadow_base[i]);
+     }
+   free(shadow_base);
+   shadow_base = NULL;
+   shadow_num = 0;
+}
+
+static void
+_ecore_x_window_tree_shadow_populate(void)
+{
+   Ecore_X_Window   *roots;
+   int               i, num;
+   
+   roots = ecore_x_window_root_list(&num);
+   if (roots)
+     {
+       shadow_base = calloc(1, sizeof(Shadow *) * num);
+       if (shadow_base)
+         {
+            shadow_num = num;
+            for (i = 0; i < num; i++)
+              shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
+         }
+       free(roots);
+     }
+}
+
+/*
+static int shadow_count = 0;
+
+static void
+_ecore_x_window_tree_shadow_start(void)
+{
+   shadow_count++;
+   if (shadow_count > 1) return;
+   _ecore_x_window_tree_shadow_populate();
+}
+
+static void
+_ecore_x_window_tree_shadow_stop(void)
+{
+   shadow_count--;
+   if (shadow_count != 0) return;
+   _ecore_x_window_tree_shadow_free();
+}
+*/
+
+static Shadow *
+_ecore_x_window_shadow_tree_find_shadow(Shadow *s, Window win)
+{
+   Shadow *ss;
+   int i;
+
+   if (s->win == win) return s;
+   if (s->children)
+     {
+       for (i = 0; i < s->children_num; i++)
+         {
+            if (!s->children[i]) continue;
+            if ((ss = _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
+              return ss;
+         }
+     }
+   return NULL;
+}
+
+static Shadow *
+_ecore_x_window_shadow_tree_find(Window base)
+{
+   Shadow *s;
+   int i;
+
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
+         return s;
+     }
+   return NULL;
+}
+
+static Window
+_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, int bx, int by, int x, int y,
+                                            Ecore_X_Window *skip, int skip_num)
+{
+   Window child;
+   int i, j;
+   int wx, wy;
+   
+   wx = s->x + bx;
+   wy = s->y + by;
+   if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
+     return 0;
+   if (s->children)
+     {
+       int skipit = 0;
+       
+       for (i = s->children_num - 1; i >= 0; --i)
+         {
+            if (!s->children[i]) continue;
+            skipit = 0;
+            if (skip)
+              {
+                 for (j = 0; j < skip_num; j++)
+                   {
+                      if (s->children[i]->win == skip[j])
+                        {
+                           skipit = 1;
+                           goto onward;
+                        }
+                   }
+              }
+            onward:
+            if (!skipit)
+              {
+                 if ((child = _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num)))
+                   {
+                      return child;
+                   }
+              }
+         }
+     }
+   return s->win;
+}
+
+static Window
+_ecore_x_window_shadow_tree_at_xy_get(Window base, int bx, int by, int x, int y,
+                                     Ecore_X_Window *skip, int skip_num)
+{
+   Shadow *s;
+   
+   if (!shadow_base)
+     {
+       _ecore_x_window_tree_shadow_populate();
+       if (!shadow_base) return 0;
+     }
+   s = _ecore_x_window_shadow_tree_find(base);
+   if (!s) return 0;
+   return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num);
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but skips the windows in the list. This uses a shadow tree built from the
+ * window tree that is only updated the first time
+ * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
+ * it is called after a  ecore_x_window_shadow_tree_flush()
+ * @param   base The base window to start searching from (normally root).
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return  The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num);
+}
+
+/**
+ * Retrieves the parent window a given window has. This uses the shadow window
+ * tree.
+ * @param   root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
+ * @param   win The window to get the parent window of
+ * @return  The parent window of @p win
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_shadow_parent_get(Ecore_X_Window root __UNUSED__, Ecore_X_Window win)
+{
+   Shadow *s;
+   int i;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!shadow_base)
+     {
+       _ecore_x_window_tree_shadow_populate();
+       if (!shadow_base) return 0;
+     }
+   for (i = 0; i < shadow_num; i++)
+     {
+       if (!shadow_base[i]) continue;
+       s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
+       if (s)
+         {
+            if (!s->parent) return 0;
+            return s->parent->win;
+         }
+     }
+   return 0;
+}
+
+/**
+ * Flushes the window shadow tree so nothing is stored.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI void
+ecore_x_window_shadow_tree_flush(void)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   _ecore_x_window_tree_shadow_free();
+}
+
+/**
+ * Retrieves the root window a given window is on.
+ * @param   win The window to get the root window of
+ * @return  The root window of @p win
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_root_get(Ecore_X_Window win)
+{
+   XWindowAttributes att;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
+   return att.root;
+}
+
+static Window
+_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
+                         Ecore_X_Window *skip, int skip_num)
+{
+   Window           *list = NULL;
+   Window            parent_win = 0, child = 0, root_win = 0;
+   int               i, j, wx, wy, ww, wh;
+   unsigned int      num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!ecore_x_window_visible_get(base))
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh);
+   wx += bx;
+   wy += by;
+
+   if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh))))
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
+     return base;
+
+   if (list)
+     {
+       int skipit = 0;
+       
+       for (i = num - 1; i >= 0; --i)
+         {
+            skipit = 0;
+            
+            if (skip)
+              {
+                 for (j = 0; j < skip_num; j++)
+                   {
+                      if (list[i] == skip[j])
+                        {
+                           skipit = 1;
+                           goto onward;
+                        }
+                   }
+              }
+            onward:
+            if (!skipit)
+              {
+                 if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num)))
+                   {
+                      XFree(list);
+                      return child;
+                   }
+              }
+         }
+       XFree(list);
+     }
+   return base;
+}
+
+/**
+ * Retrieves the top, visible window at the given location.
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return  The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_get(int x, int y)
+{
+   Ecore_X_Window    win, root;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* FIXME: Proper function to determine current root/virtual root
+    * window missing here */
+   root = DefaultRootWindow(_ecore_x_disp);
+   
+   ecore_x_grab();
+   win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
+   ecore_x_ungrab();
+   
+   return win ? win : root;
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but skips the windows in the list.
+ * @param   x The given X position.
+ * @param   y The given Y position.
+ * @return  The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num)
+{
+   Ecore_X_Window    win, root;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* FIXME: Proper function to determine current root/virtual root
+    * window missing here */
+   root = DefaultRootWindow(_ecore_x_disp);
+   
+   ecore_x_grab();
+   win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
+   ecore_x_ungrab();
+   
+   return win ? win : root;
+}
+
+EAPI Ecore_X_Window
+ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y)
+{
+   Ecore_X_Window    win;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_grab();
+   win = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
+   ecore_x_ungrab();
+   
+   return win ? win : begin;
+}
+
+/**
+ * Retrieves the parent window of the given window.
+ * @param   win The given window.
+ * @return  The parent window of @p win.
+ * @ingroup Ecore_X_Window_Parent_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_parent_get(Ecore_X_Window win)
+{
+   Window         root, parent, *children = NULL;
+   unsigned int   num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XQueryTree(_ecore_x_disp, win, &root, &parent, &children, &num))
+      return 0;
+   if (children)
+      XFree(children);
+
+   return parent;
+}
+
+/**
+ * Sets the background color of the given window.
+ * @param win   The given window
+ * @param r     red value (0...65536, 16 bits)
+ * @param g     green value (0...65536, 16 bits)
+ * @param b     blue value (0...65536, 16 bits)
+ */
+EAPI void
+ecore_x_window_background_color_set(Ecore_X_Window win, unsigned short r,
+                                   unsigned short g, unsigned short b)
+{
+   XSetWindowAttributes attr;
+   Colormap map;
+   XColor col;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   col.red = r;
+   col.green = g;
+   col.blue = b;
+
+   map = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp));
+   XAllocColor(_ecore_x_disp, map, &col);
+
+   attr.background_pixel = col.pixel;
+   XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr);
+}
+
+EAPI void
+ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
+{
+   XSetWindowAttributes att;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   att.win_gravity = grav;
+   XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att);
+}
+
+EAPI void
+ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
+{
+   XSetWindowAttributes att;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   att.bit_gravity = grav;
+   XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att);
+}
+
+EAPI void
+ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pmap)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap);
+}
+
+EAPI void
+ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XClearArea(_ecore_x_disp, win, x, y, w, h, False);
+}
+
+EAPI void
+ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XClearArea(_ecore_x_disp, win, x, y, w, h, True);
+}
+
+EAPI void
+ecore_x_window_override_set(Ecore_X_Window win, int override)
+{
+   XSetWindowAttributes att;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   att.override_redirect = override;
+   XChangeWindowAttributes(_ecore_x_disp, win, CWOverrideRedirect, &att);
+}
+
+#ifdef ECORE_XRENDER   
+static Ecore_X_Window
+_ecore_x_window_argb_internal_new(Ecore_X_Window parent, int x, int y, int w, int h, int override, int saveunder)
+{
+   Window                win;
+   XSetWindowAttributes  attr;
+   XWindowAttributes     att;
+   XVisualInfo          *xvi;
+   XVisualInfo           vi_in;
+   int                   nvi, i, scr = 0;
+   XRenderPictFormat    *fmt;
+   Visual               *vis;
+   
+   if (parent == 0)
+     {
+       parent = DefaultRootWindow(_ecore_x_disp);
+       scr = DefaultScreen(_ecore_x_disp);
+     }
+   else
+     {
+       /* ewww - round trip */
+       XGetWindowAttributes(_ecore_x_disp, parent, &att);
+       for (i = 0; i < ScreenCount(_ecore_x_disp); i++)
+         {
+            if (att.screen == ScreenOfDisplay(_ecore_x_disp, i))
+              {
+                 scr = i;
+                 break;
+              }
+         }
+     }
+   vi_in.screen = scr;
+   vi_in.depth = 32;
+   vi_in.class = TrueColor;
+   xvi = XGetVisualInfo(_ecore_x_disp,
+                       VisualScreenMask |
+                       VisualDepthMask |
+                       VisualClassMask,
+                       &vi_in,
+                       &nvi);
+   if (xvi == NULL) return 0;
+   vis = NULL;
+   for (i = 0; i < nvi; i++)
+     {
+       fmt = XRenderFindVisualFormat(_ecore_x_disp, xvi[i].visual);
+       if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
+         {
+            vis = xvi[i].visual;
+            break;
+         }
+     }
+   XFree (xvi);
+   
+   attr.backing_store         = NotUseful;
+   attr.override_redirect     = override;
+   attr.colormap              = XCreateColormap(_ecore_x_disp, parent,
+                                               vis, AllocNone);
+   attr.border_pixel          = 0;
+   attr.background_pixmap     = None;
+   attr.bit_gravity           = NorthWestGravity;
+   attr.win_gravity           = NorthWestGravity;
+   attr.save_under            = saveunder;
+   attr.do_not_propagate_mask = NoEventMask;
+   attr.event_mask            = KeyPressMask |
+                                KeyReleaseMask |
+                                ButtonPressMask |
+                                ButtonReleaseMask |
+                                EnterWindowMask |
+                                LeaveWindowMask |
+                                PointerMotionMask |
+                                ExposureMask |
+                                VisibilityChangeMask |
+                                StructureNotifyMask |
+                                FocusChangeMask |
+                                PropertyChangeMask |
+                                ColormapChangeMask;
+   win = XCreateWindow(_ecore_x_disp, parent,
+                      x, y, w, h, 0,
+                      32, 
+                      InputOutput, 
+                      vis,
+                      CWBackingStore |
+                      CWOverrideRedirect | 
+                      CWColormap |
+                      CWBorderPixel |
+                      CWBackPixmap | 
+                      CWSaveUnder | 
+                      CWDontPropagate | 
+                      CWEventMask |
+                      CWBitGravity |
+                      CWWinGravity,
+                      &attr);
+   XFreeColormap(_ecore_x_disp, attr.colormap);
+
+   if (parent == DefaultRootWindow(_ecore_x_disp)) ecore_x_window_defaults_set(win);
+   return win;
+}
+#endif
+
+EAPI int
+ecore_x_window_argb_get(Ecore_X_Window win)
+{
+#ifdef ECORE_XRENDER   
+   XWindowAttributes att;
+   XRenderPictFormat *fmt;
+
+   att.visual = 0;
+   if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
+   fmt = XRenderFindVisualFormat(_ecore_x_disp, att.visual);
+   if (!fmt) return 0;
+   if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask)) return 1;
+   return 0;
+#else
+   return 0;
+#endif   
+}
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_manager_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+#ifdef ECORE_XRENDER   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
+#else
+   return 0;
+#endif   
+}
+
+/**
+ * Creates a new window.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+#ifdef ECORE_XRENDER   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 0, 0);
+#else
+   return 0;
+#endif   
+}
+
+/**
+ * Creates a window with the override redirect attribute set to @c True.
+ * @param   parent The parent window to use.  If @p parent is @c 0, the root
+ *                 window of the default display is used.
+ * @param   x      X position.
+ * @param   y      Y position.
+ * @param   w      Width.
+ * @param   h      Height.
+ * @return  The new window handle.
+ * @ingroup Ecore_X_Window_Create_Group
+ */
+EAPI Ecore_X_Window
+ecore_x_window_override_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
+{
+#ifdef ECORE_XRENDER   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
+#else
+   return 0;
+#endif   
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_window_prop.c b/src/lib/ecore_x/xlib/ecore_x_window_prop.c
new file mode 100644 (file)
index 0000000..cf81c3c
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+#include <inttypes.h>
+#include <limits.h>
+
+#define _ATOM_SET_CARD32(win, atom, p_val, cnt) \
+   XChangeProperty(_ecore_x_disp, win, atom, XA_CARDINAL, 32, PropModeReplace, \
+                   (unsigned char *)p_val, cnt)
+
+/*
+ * Set CARD32 (array) property
+ */
+EAPI void
+ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                              unsigned int *val, unsigned int num)
+{
+#if SIZEOF_INT == SIZEOF_LONG
+   _ATOM_SET_CARD32(win, atom, val, num);
+#else
+   long               *v2;
+   unsigned int        i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   v2 = malloc(num * sizeof(long));
+   if (!v2)
+      return;
+   for (i = 0; i < num; i++)
+      v2[i] = val[i];
+   _ATOM_SET_CARD32(win, atom, v2, num);
+   free(v2);
+#endif
+}
+
+/*
+ * Get CARD32 (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                              unsigned int *val, unsigned int len)
+{
+   unsigned char      *prop_ret;
+   Atom                type_ret;
+   unsigned long       bytes_after, num_ret;
+   int                 format_ret;
+   unsigned int        i;
+   int                 num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   prop_ret = NULL;
+   if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
+                         XA_CARDINAL, &type_ret, &format_ret, &num_ret,
+                         &bytes_after, &prop_ret) != Success)
+      return -1;
+
+   if (type_ret != XA_CARDINAL || format_ret != 32)
+     {
+       num = -1;
+     }
+   else if (num_ret == 0 || !prop_ret)
+     {
+       num = 0;
+     }
+   else
+     {
+       if (num_ret < len)
+          len = num_ret;
+       for (i = 0; i < len; i++)
+          val[i] = ((unsigned long *)prop_ret)[i];
+       num = len;
+     }
+   if (prop_ret)
+      XFree(prop_ret);
+
+   return num;
+}
+
+/*
+ * Get CARD32 (array) property of any length
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_card32_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                                   unsigned int **plst)
+{
+   unsigned char      *prop_ret;
+   Atom                type_ret;
+   unsigned long       bytes_after, num_ret;
+   int                 format_ret;
+   unsigned int        i, *val;
+   int                 num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   *plst = NULL;
+   prop_ret = NULL;
+   if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
+                         XA_CARDINAL, &type_ret, &format_ret, &num_ret,
+                         &bytes_after, &prop_ret) != Success)
+      return -1;
+
+   if (type_ret != XA_CARDINAL || format_ret != 32)
+     {
+       num = -1;
+     }
+   else if (num_ret == 0 || !prop_ret)
+     {
+       num = 0;
+     }
+   else
+     {
+       val = malloc(num_ret * sizeof(unsigned int));
+       for (i = 0; i < num_ret; i++)
+          val[i] = ((unsigned long *)prop_ret)[i];
+       num = num_ret;
+       *plst = val;
+     }
+   if (prop_ret)
+      XFree(prop_ret);
+
+   return num;
+}
+
+/*
+ * Set X ID (array) property
+ */
+EAPI void
+ecore_x_window_prop_xid_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                           Ecore_X_Atom type, Ecore_X_ID * lst,
+                           unsigned int num)
+{
+#if SIZEOF_INT == SIZEOF_LONG
+   XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
+                  (unsigned char *)lst, num);
+#else
+   unsigned long      *pl;
+   unsigned int        i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   pl = malloc(num * sizeof(long));
+   if (!pl)
+      return;
+   for (i = 0; i < num; i++)
+      pl[i] = lst[i];
+   XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace,
+                  (unsigned char *)pl, num);
+   free(pl);
+#endif
+}
+
+/*
+ * Get X ID (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_xid_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                           Ecore_X_Atom type, Ecore_X_ID * lst,
+                           unsigned int len)
+{
+   unsigned char      *prop_ret;
+   Atom                type_ret;
+   unsigned long       bytes_after, num_ret;
+   int                 format_ret;
+   int                 num;
+   unsigned            i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   prop_ret = NULL;
+   if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
+                         type, &type_ret, &format_ret, &num_ret,
+                         &bytes_after, &prop_ret) != Success)
+      return -1;
+
+   if (type_ret != type || format_ret != 32)
+     {
+       num = -1;
+     }
+   else if (num_ret == 0 || !prop_ret)
+     {
+       num = 0;
+     }
+   else
+     {
+       if (num_ret < len)
+          len = num_ret;
+       for (i = 0; i < len; i++)
+          lst[i] = ((unsigned long *)prop_ret)[i];
+       num = len;
+     }
+   if (prop_ret)
+      XFree(prop_ret);
+
+   return num;
+}
+
+/*
+ * Get X ID (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_xid_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                                Ecore_X_Atom type, Ecore_X_ID ** val)
+{
+   unsigned char      *prop_ret;
+   Atom                type_ret;
+   unsigned long       bytes_after, num_ret;
+   int                 format_ret;
+   Ecore_X_Atom       *alst;
+   int                 num;
+   unsigned            i;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   *val = NULL;
+   prop_ret = NULL;
+   if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
+                         type, &type_ret, &format_ret, &num_ret,
+                         &bytes_after, &prop_ret) != Success)
+      return -1;
+
+   if (type_ret != type || format_ret != 32)
+     {
+       num = -1;
+     }
+   else if (num_ret == 0 || !prop_ret)
+     {
+       num = 0;
+     }
+   else
+     {
+       alst = malloc(num_ret * sizeof(Ecore_X_ID));
+       for (i = 0; i < num_ret; i++)
+          alst[i] = ((unsigned long *)prop_ret)[i];
+       num = num_ret;
+       *val = alst;
+     }
+   if (prop_ret)
+      XFree(prop_ret);
+
+   return num;
+}
+
+/*
+ * Remove/add/toggle X ID list item.
+ */
+EAPI void
+ecore_x_window_prop_xid_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
+                                   Ecore_X_Atom type, Ecore_X_ID item, int op)
+{
+   Ecore_X_ID         *lst;
+   int                 i, num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst);
+   if (num < 0)
+      return;                  /* Error - assuming invalid window */
+
+   /* Is it there? */
+   for (i = 0; i < num; i++)
+     {
+       if (lst[i] == item)
+          break;
+     }
+
+   if (i < num)
+     {
+       /* Was in list */
+       if (op == ECORE_X_PROP_LIST_ADD)
+          goto done;
+       /* Remove it */
+       num--;
+       for (; i < num; i++)
+          lst[i] = lst[i + 1];
+     }
+   else
+     {
+       /* Was not in list */
+       if (op == ECORE_X_PROP_LIST_REMOVE)
+          goto done;
+       /* Add it */
+       num++;
+       lst = realloc(lst, num * sizeof(Ecore_X_ID));
+       lst[i] = item;
+     }
+
+   ecore_x_window_prop_xid_set(win, atom, type, lst, num);
+
+ done:
+   if (lst)
+      free(lst);
+}
+
+/*
+ * Set Atom (array) property
+ */
+EAPI void
+ecore_x_window_prop_atom_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                            Ecore_X_Atom * lst, unsigned int num)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_xid_set(win, atom, XA_ATOM, lst, num);
+}
+
+/*
+ * Get Atom (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_atom_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                            Ecore_X_Atom * lst, unsigned int len)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_window_prop_xid_get(win, atom, XA_ATOM, lst, len);
+}
+
+/*
+ * Get Atom (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_atom_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                                 Ecore_X_Atom ** plst)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_window_prop_xid_list_get(win, atom, XA_ATOM, plst);
+}
+
+/*
+ * Remove/add/toggle atom list item.
+ */
+EAPI void
+ecore_x_window_prop_atom_list_change(Ecore_X_Window win, Ecore_X_Atom atom,
+                                    Ecore_X_Atom item, int op)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_xid_list_change(win, atom, XA_ATOM, item, op);
+}
+
+/*
+ * Set Window (array) property
+ */
+EAPI void
+ecore_x_window_prop_window_set(Ecore_X_Window win, Ecore_X_Atom atom,
+                              Ecore_X_Window * lst, unsigned int num)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   ecore_x_window_prop_xid_set(win, atom, XA_WINDOW, lst, num);
+}
+
+/*
+ * Get Window (array) property
+ *
+ * At most len items are returned in val.
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_window_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                              Ecore_X_Window * lst, unsigned int len)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_window_prop_xid_get(win, atom, XA_WINDOW, lst, len);
+}
+
+/*
+ * Get Window (array) property
+ *
+ * If the property was successfully fetched the number of items stored in
+ * val is returned, otherwise -1 is returned.
+ * The returned array must be freed with free().
+ * Note: Return value 0 means that the property exists but has no elements.
+ */
+EAPI int
+ecore_x_window_prop_window_list_get(Ecore_X_Window win, Ecore_X_Atom atom,
+                                   Ecore_X_Window ** plst)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   return ecore_x_window_prop_xid_list_get(win, atom, XA_WINDOW, plst);
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI Ecore_X_Atom
+ecore_x_window_prop_any_type(void)
+{
+   return AnyPropertyType;
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI void
+ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size, void *data, int number)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
+   if (size != 32)
+     XChangeProperty(_ecore_x_disp, win, property, type, size, PropModeReplace,
+                    (unsigned char *)data, number);
+   else
+     {
+       unsigned long *dat;
+       int            i, *ptr;
+       
+       dat = malloc(sizeof(unsigned long) * number);
+       if (dat)
+         {
+            for (ptr = (int *)data, i = 0; i < number; i++) dat[i] = ptr[i];
+            XChangeProperty(_ecore_x_disp, win, property, type, size, 
+                            PropModeReplace, (unsigned char *)dat, number);
+            free(dat);
+         }
+     }
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI int
+ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size __UNUSED__, unsigned char **data, int *num)
+{
+   Atom type_ret = 0;
+   int ret, size_ret = 0;
+   unsigned long num_ret = 0, bytes = 0, i;
+   unsigned char *prop_ret = NULL;
+
+   /* make sure these are initialized */
+   if (num) *num = 0;
+
+   if (data)
+     *data = NULL;
+   else /* we can't store the retrieved data, so just return */
+     return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!win) win = DefaultRootWindow(_ecore_x_disp);
+
+   ret = XGetWindowProperty(_ecore_x_disp, win, property, 0, LONG_MAX,
+                            False, type, &type_ret, &size_ret,
+                            &num_ret, &bytes, &prop_ret);
+
+   if (ret != Success)
+       return 0;
+
+   if (!num_ret) {
+      XFree(prop_ret);
+      return 0;
+   }
+   
+   if (!(*data = malloc(num_ret * size_ret / 8))) {
+      XFree(prop_ret);
+      return 0;
+   }
+   
+   switch (size_ret) {
+      case 8:
+        for (i = 0; i < num_ret; i++)
+          (*data)[i] = prop_ret[i];
+        break;
+      case 16:
+        for (i = 0; i < num_ret; i++)
+          ((unsigned short *) *data)[i] = ((unsigned short *) prop_ret)[i];
+        break;
+      case 32:
+        for (i = 0; i < num_ret; i++)
+          ((unsigned int *) *data)[i] = ((unsigned long *) prop_ret)[i];
+        break;
+   }
+
+   XFree(prop_ret);
+
+   if (num) *num = num_ret;
+   return size_ret;
+}
+
+EAPI void
+ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XDeleteProperty(_ecore_x_disp, win, property);
+}
+
+EAPI Ecore_X_Atom *
+ecore_x_window_prop_list(Ecore_X_Window win, int *num_ret)
+{
+   Ecore_X_Atom *atoms;
+   Atom *atom_ret;
+   int num = 0, i;
+       
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num_ret) *num_ret = 0;
+
+   atom_ret = XListProperties(_ecore_x_disp, win, &num);
+   if (!atom_ret) return NULL;
+
+   atoms = malloc(num * sizeof(Ecore_X_Atom));
+   if (atoms)
+     {
+       for (i = 0; i < num; i++) atoms[i] = atom_ret[i];
+       if (num_ret) *num_ret = num;
+     }
+   XFree(atom_ret);
+   return atoms;
+}
+
+/**
+ * Set a window string property.
+ * @param win The window
+ * @param type The property
+ * @param str The string
+ * 
+ * Set a window string property
+ */
+EAPI void
+ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str)
+{
+   XTextProperty       xtp;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
+   xtp.value = (unsigned char *)str;
+   xtp.format = 8;
+   xtp.encoding = ECORE_X_ATOM_UTF8_STRING;
+   xtp.nitems = strlen(str);
+   XSetTextProperty(_ecore_x_disp, win, &xtp, type);
+}
+
+/**
+ * Get a window string property.
+ * @param win The window
+ * @param type The property
+ * 
+ * Return window string property of a window. String must be free'd when done.
+ */
+EAPI char *
+ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type)
+{
+   XTextProperty       xtp;
+   char               *str = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
+   if (XGetTextProperty(_ecore_x_disp, win, &xtp, type))
+     {
+       int      items;
+       char   **list = NULL;
+       Status   s;
+       
+       if (xtp.encoding == ECORE_X_ATOM_UTF8_STRING)
+         {
+            str = strdup((char *)xtp.value);
+         }
+       else
+         {
+#ifdef X_HAVE_UTF8_STRING
+            s = Xutf8TextPropertyToTextList(_ecore_x_disp, &xtp,
+                                            &list, &items);
+#else
+            s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp,
+                                          &list, &items);
+#endif
+            if ((s == XLocaleNotSupported) ||
+                (s == XNoMemory) || (s == XConverterNotFound))
+              {
+                 str = strdup((char *)xtp.value);
+              }
+            else if ((s >= Success) && (items > 0))
+              {
+                 str = strdup(list[0]);
+              }
+            if (list)
+              XFreeStringList(list);
+         }
+       XFree(xtp.value);
+     }
+   return str;
+}
+
+EAPI int
+ecore_x_window_prop_protocol_isset(Ecore_X_Window win,
+                                   Ecore_X_WM_Protocol protocol)
+{
+   Atom proto, *protos = NULL;
+   int i, ret = 0, protos_count = 0;
+
+   /* check for invalid values */
+   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
+       return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   proto = _ecore_x_atoms_wm_protocols[protocol];
+
+   if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
+       return ret;
+
+   for (i = 0; i < protos_count; i++)
+       if (protos[i] == proto)
+         {
+            ret = 1;
+            break;
+         }
+
+   XFree(protos);
+
+   return ret;
+}
+
+/**
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ */
+EAPI Ecore_X_WM_Protocol *
+ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, int *num_ret)
+{
+   Atom *protos = NULL;
+   int i, protos_count = 0;
+   Ecore_X_WM_Protocol *prot_ret = NULL;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
+     return NULL;
+
+   if ((!protos) || (protos_count <= 0)) return NULL;
+   prot_ret = calloc(1, protos_count * sizeof(Ecore_X_WM_Protocol));
+   if (!prot_ret)
+     {
+       XFree(protos);
+       return NULL;
+     }
+   for (i = 0; i < protos_count; i++)
+     {
+       Ecore_X_WM_Protocol j;
+       
+       prot_ret[i] = -1;
+       for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++)
+         {
+            if (_ecore_x_atoms_wm_protocols[j] == protos[i])
+              prot_ret[i] = j;
+         }
+     }
+   XFree(protos);
+   *num_ret = protos_count;
+   return prot_ret;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_window_shape.c b/src/lib/ecore_x/xlib/ecore_x_window_shape.c
new file mode 100644 (file)
index 0000000..c6c0314
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+/**
+ * @defgroup Ecore_X_Window_Shape X Window Shape Functions
+ *
+ * These functions use the shape extension of the X server to change
+ * shape of given windows.
+ */
+
+/**
+ * Sets the shape of the given window to that given by the pixmap @p mask.
+ * @param   win  The given window.
+ * @param   mask A 2-bit depth pixmap that provides the new shape of the
+ *               window.
+ * @ingroup Ecore_X_Window_Shape
+ */
+EAPI void
+ecore_x_window_shape_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XShapeCombineMask(_ecore_x_disp, win, ShapeBounding, 0, 0, mask, ShapeSet);
+}
+
+EAPI void
+ecore_x_window_shape_window_set(Ecore_X_Window win, Ecore_X_Window shape_win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, 0, 0, shape_win, ShapeBounding, ShapeSet);
+}
+
+EAPI void
+ecore_x_window_shape_window_set_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, x, y, shape_win, ShapeBounding, ShapeSet);
+}
+
+EAPI void
+ecore_x_window_shape_rectangle_set(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   XRectangle rect;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   rect.x = x;
+   rect.y = y;
+   rect.width = w;
+   rect.height = h;
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, Unsorted);
+}
+
+EAPI void
+ecore_x_window_shape_rectangles_set(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num)
+{
+   XRectangle *rect = NULL;
+   int i;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num > 0)
+     {
+       rect = malloc(sizeof(XRectangle) * num);
+       if (rect)
+         {
+            for (i = 0; i < num; i++)
+              {
+                 rect[i].x = rects[i].x;
+                 rect[i].y = rects[i].y;
+                 rect[i].width = rects[i].width;
+                 rect[i].height = rects[i].height;
+              }
+         }
+       else
+         num = 0;
+     }
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, rect, num, ShapeSet, Unsorted);
+   if (rect) free(rect);
+}
+
+EAPI void
+ecore_x_window_shape_window_add(Ecore_X_Window win, Ecore_X_Window shape_win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, 0, 0, shape_win, ShapeBounding, ShapeUnion);
+}
+
+EAPI void
+ecore_x_window_shape_window_add_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, x, y, shape_win, ShapeBounding, ShapeUnion);
+}
+
+EAPI void
+ecore_x_window_shape_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   XRectangle rect;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   rect.x = x;
+   rect.y = y;
+   rect.width = w;
+   rect.height = h;
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, Unsorted);
+}
+
+EAPI void
+ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h)
+{
+   XRectangle rect;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   rect.x = x;
+   rect.y = y;
+   rect.width = w;
+   rect.height = h;
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeIntersect, Unsorted);
+}
+
+EAPI void
+ecore_x_window_shape_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num)
+{
+   XRectangle *rect = NULL;
+   int i;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (num > 0)
+     {
+       rect = malloc(sizeof(XRectangle) * num);
+       if (rect)
+         {
+            for (i = 0; i < num; i++)
+              {
+                 rect[i].x = rects[i].x;
+                 rect[i].y = rects[i].y;
+                 rect[i].width = rects[i].width;
+                 rect[i].height = rects[i].height;
+              }
+         }
+       else
+         num = 0;
+     }
+   XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, rect, num, ShapeUnion, Unsorted);
+   if (rect) free(rect);
+}
+
+EAPI Ecore_X_Rectangle *
+ecore_x_window_shape_rectangles_get(Ecore_X_Window win, int *num_ret)
+{
+   XRectangle *rect;
+   Ecore_X_Rectangle *rects = NULL;
+   int i, num = 0, ord;
+   
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   rect = XShapeGetRectangles(_ecore_x_disp, win, ShapeBounding, &num, &ord);
+   if (rect)
+     {
+       rects = malloc(sizeof(Ecore_X_Rectangle) * num);
+       if (rects)
+         {
+            for (i = 0; i < num; i++)
+              {
+                 rects[i].x = rect[i].x;
+                 rects[i].y = rect[i].y;
+                 rects[i].width = rect[i].width;
+                 rects[i].height = rect[i].height;
+              }
+         }
+       XFree(rect);
+     }
+   if (num_ret) *num_ret = num;
+   return rects;
+}
+
+EAPI void
+ecore_x_window_shape_events_select(Ecore_X_Window win, int on)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (on)
+     XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
+   else
+     XShapeSelectInput(_ecore_x_disp, win, 0);
+}
+
+/**
+ * Sets the input shape of the given window to that given by the pixmap @p mask.
+ * @param   win  The given window.
+ * @param   mask A 2-bit depth pixmap that provides the new input shape of the
+ *               window.
+ * @ingroup Ecore_X_Window_Shape
+ */
+EAPI void
+ecore_x_window_shape_input_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef ShapeInput
+   XShapeCombineMask(_ecore_x_disp, win, ShapeInput, 0, 0, mask, ShapeSet);
+#else   
+   XShapeCombineMask(_ecore_x_disp, win, ShapeBounding, 0, 0, mask, ShapeSet);
+#endif
+}
+
diff --git a/src/lib/ecore_x/xlib/ecore_x_xi2.c b/src/lib/ecore_x/xlib/ecore_x_xi2.c
new file mode 100644 (file)
index 0000000..5812728
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+#ifdef ECORE_XI2
+#include "Ecore_Input.h"
+#endif
+
+int _ecore_x_xi2_opcode = -1;
+
+#ifdef ECORE_XI2
+static XIDeviceInfo *_ecore_x_xi2_devs = NULL;
+static int _ecore_x_xi2_num = 0;
+#endif
+
+void
+_ecore_x_input_init(void)
+{
+#ifdef ECORE_XI2
+   int event, error;
+   int major = 2, minor = 0;
+   
+   if (!XQueryExtension(_ecore_x_disp, "XInputExtension", 
+                        &_ecore_x_xi2_opcode, &event, &error))
+     {
+        _ecore_x_xi2_opcode = -1;
+        return;
+     }
+   
+   if (XIQueryVersion(_ecore_x_disp, &major, &minor) == BadRequest)
+     {
+        _ecore_x_xi2_opcode = -1;
+        return;
+     }
+   _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices, 
+                                     &_ecore_x_xi2_num);
+#endif   
+}
+
+void
+_ecore_x_input_shutdown(void)
+{
+#ifdef ECORE_XI2
+   if (_ecore_x_xi2_devs)
+     {
+        XIFreeDeviceInfo(_ecore_x_xi2_devs);
+        _ecore_x_xi2_devs = NULL;
+     }
+   _ecore_x_xi2_num = 0;
+   _ecore_x_xi2_opcode = -1;
+#endif   
+}
+
+void
+_ecore_x_input_handler(XEvent* xevent)
+{
+#ifdef ECORE_XI2
+   XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
+   int devid = evd->deviceid;
+   
+   //printf("deviceID = %d\n", devid);
+   switch (xevent->xcookie.evtype)
+     {
+     case XI_Motion:
+        _ecore_mouse_move
+          (evd->time,
+           0, // state
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y,
+           evd->event,
+           (evd->child ? evd->child : evd->event),
+           evd->root,
+           1, // same_screen
+           devid, 1, 1, 
+           1.0, // pressure
+           0.0, // angle
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y);
+        break;
+     case XI_ButtonPress:
+        _ecore_mouse_button
+          (ECORE_EVENT_MOUSE_BUTTON_DOWN,
+           evd->time,
+           0, // state
+           0, // button
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y,
+           evd->event,
+           (evd->child ? evd->child : evd->event),
+           evd->root,
+           1, // same_screen
+           devid, 1, 1,
+           1.0, // pressure
+           0.0, // angle
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y);
+        break;
+     case XI_ButtonRelease:
+        _ecore_mouse_button
+          (ECORE_EVENT_MOUSE_BUTTON_UP,
+           evd->time,
+           0, // state
+           0, // button
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y,
+           evd->event,
+           (evd->child ? evd->child : evd->event),
+           evd->root,
+           1, // same_screen
+           devid, 1, 1,
+           1.0, // pressure
+           0.0, // angle
+           evd->event_x, evd->event_y,
+           evd->root_x, evd->root_y);
+        break;
+     }
+#endif   
+}
+
+EAPI Eina_Bool
+ecore_x_input_multi_select(Ecore_X_Window win)
+{
+#ifdef ECORE_XI2
+   int i, find = 0;
+
+   if (!_ecore_x_xi2_devs) return 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   for (i = 0; i < _ecore_x_xi2_num; i++)
+     {
+        XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
+
+        if (dev->use == XIFloatingSlave)
+          {
+             XIEventMask eventmask;
+             unsigned char mask[1] = { 0 };
+
+             eventmask.deviceid = dev->deviceid;
+             eventmask.mask_len = sizeof(mask);
+             eventmask.mask = mask;
+             XISetMask(mask, XI_ButtonPress);
+             XISetMask(mask, XI_ButtonRelease);
+             XISetMask(mask, XI_Motion);
+             XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
+             find = 1;
+          }
+     }
+
+   return find;
+#else
+   return 0;
+#endif
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_xinerama.c b/src/lib/ecore_x/xlib/ecore_x_xinerama.c
new file mode 100644 (file)
index 0000000..cb6c8db
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/*
+ * Xinerama code
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+#include "Ecore_X_Atoms.h"
+
+#ifdef ECORE_XINERAMA
+static XineramaScreenInfo *_xin_info = NULL;
+static int _xin_scr_num = 0;
+#endif
+
+EAPI int
+ecore_x_xinerama_screen_count_get(void)
+{
+#ifdef ECORE_XINERAMA
+   int event_base, error_base;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if (_xin_info) XFree(_xin_info);
+   _xin_info = NULL;
+   if (XineramaQueryExtension(_ecore_x_disp, &event_base, &error_base))
+     {
+       _xin_info = XineramaQueryScreens(_ecore_x_disp, &_xin_scr_num);
+       if (_xin_info) return _xin_scr_num;
+     }
+#endif
+   return 0;
+}
+
+EAPI int
+ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef ECORE_XINERAMA
+   if (_xin_info)
+     {
+       int i;
+       
+       for (i = 0; i < _xin_scr_num; i++)
+         {
+            if (_xin_info[i].screen_number == screen)
+              {
+                 if (x) *x = _xin_info[i].x_org;
+                 if (y) *y = _xin_info[i].y_org;
+                 if (w) *w = _xin_info[i].width;
+                 if (h) *h = _xin_info[i].height;
+                 return 1;
+              }
+         }
+     }
+#endif
+   if (x) *x = 0;
+   if (y) *y = 0;
+   if (w) *w = DisplayWidth(_ecore_x_disp, 0);
+   if (h) *h = DisplayHeight(_ecore_x_disp, 0);
+   return 0;
+}
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644 (file)
index 0000000..005e1c9
--- /dev/null
@@ -0,0 +1,25 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_con \
+@EINA_CFLAGS@ \
+@CHECK_CFLAGS@
+
+if EFL_ENABLE_TESTS
+
+check_PROGRAMS = ecore_suite
+
+ecore_suite_SOURCES = \
+ecore_suite.c \
+ecore_test_ecore.c \
+ecore_test_ecore_con.c
+
+ecore_suite_LDADD = \
+@CHECK_LIBS@ \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la
+
+endif
+
+EXTRA_DIST = ecore_suite.h
diff --git a/src/tests/ecore_suite.c b/src/tests/ecore_suite.c
new file mode 100644 (file)
index 0000000..9c7e199
--- /dev/null
@@ -0,0 +1,102 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <Ecore.h>
+
+#include "ecore_suite.h"
+
+typedef struct _Ecore_Test_Case Ecore_Test_Case;
+
+struct _Ecore_Test_Case
+{
+   const char *test_case;
+   void      (*build)(TCase *tc);
+};
+
+static const Ecore_Test_Case etc[] = {
+  { "Ecore", ecore_test_ecore },
+  { "Ecore_Con", ecore_test_ecore_con },
+  { NULL, NULL }
+};
+
+static void
+_list_tests(void)
+{
+  const Ecore_Test_Case *itr;
+
+   itr = etc;
+   fputs("Available Test Cases:\n", stderr);
+   for (; itr->test_case != NULL; itr++)
+     fprintf(stderr, "\t%s\n", itr->test_case);
+}
+static Eina_Bool
+_use_test(int argc, const char **argv, const char *test_case)
+{
+   if (argc < 1)
+     return 1;
+
+   for (; argc > 0; argc--, argv++)
+     if (strcmp(test_case, *argv) == 0)
+       return 1;
+   return 0;
+}
+
+static Suite *
+ecore_suite_build(int argc, const char **argv)
+{
+   TCase *tc;
+   Suite *s;
+   int i;
+
+   s = suite_create("Ecore");
+
+   for (i = 0; etc[i].test_case != NULL; ++i)
+     {
+       if (!_use_test(argc, argv, etc[i].test_case)) continue;
+       tc = tcase_create(etc[i].test_case);
+
+       etc[i].build(tc);
+
+       suite_add_tcase(s, tc);
+       tcase_set_timeout(tc, 0);
+     }
+
+   return s;
+}
+
+int
+main(int argc, char **argv)
+{
+   Suite *s;
+   SRunner *sr;
+   int i, failed_count;
+
+   for (i = 1; i < argc; i++)
+     if ((strcmp(argv[i], "-h") == 0) ||
+        (strcmp(argv[i], "--help") == 0))
+       {
+         fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n",
+                 argv[0]);
+         _list_tests();
+         return 0;
+       }
+     else if ((strcmp(argv[i], "-l") == 0) ||
+             (strcmp(argv[i], "--list") == 0))
+       {
+         _list_tests();
+         return 0;
+       }
+
+   s = ecore_suite_build(argc - 1, (const char **)argv + 1);
+   sr = srunner_create(s);
+
+   srunner_run_all(sr, CK_NORMAL);
+   failed_count = srunner_ntests_failed(sr);
+   srunner_free(sr);
+
+   return (failed_count == 0) ? 0 : 255;
+}
diff --git a/src/tests/ecore_suite.h b/src/tests/ecore_suite.h
new file mode 100644 (file)
index 0000000..2e35ee7
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ECORE_SUITE_H
+#define _ECORE_SUITE_H
+
+#include <check.h>
+
+void ecore_test_ecore(TCase *tc);
+void ecore_test_ecore_con(TCase *tc);
+
+
+#endif /* _ECORE_SUITE_H */
diff --git a/src/tests/ecore_test_ecore.c b/src/tests/ecore_test_ecore.c
new file mode 100644 (file)
index 0000000..fc0c668
--- /dev/null
@@ -0,0 +1,241 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore.h>
+#include <unistd.h>
+
+#include "ecore_suite.h"
+
+static int
+_quit_cb(void *data)
+{
+   Eina_Bool *val = data;
+   *val = EINA_TRUE;
+   ecore_main_loop_quit();
+   return 0;
+}
+
+static int
+_dummy_cb(void *data)
+{
+   return (int)(long)data;
+}
+
+START_TEST(ecore_test_ecore_init)
+{
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+START_TEST(ecore_test_ecore_main_loop)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Timer *timer;
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   timer = ecore_timer_add(0.0, _quit_cb, &did);
+   fail_if(timer == NULL);
+
+   ecore_main_loop_begin();
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+START_TEST(ecore_test_ecore_main_loop_idler)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Idler *idler;
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   idler = ecore_idler_add(_quit_cb, &did);
+   fail_if(idler == NULL);
+
+   ecore_main_loop_begin();
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+START_TEST(ecore_test_ecore_main_loop_idle_enterer)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Idle_Enterer *idle_enterer;
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   idle_enterer = ecore_idle_enterer_add(_quit_cb, &did);
+   fail_if(idle_enterer == NULL);
+
+   ecore_main_loop_begin();
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+START_TEST(ecore_test_ecore_main_loop_idle_exiter)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Timer *timer;
+   Ecore_Idle_Exiter *idle_exiter;
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   /* make system exit idle */
+   timer = ecore_timer_add(0.0, _dummy_cb, (void *)(long)0);
+   fail_if(timer == NULL);
+
+   idle_exiter = ecore_idle_exiter_add(_quit_cb, &did);
+   fail_if(idle_exiter == NULL);
+
+   ecore_main_loop_begin();
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+START_TEST(ecore_test_ecore_main_loop_timer)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Timer *timer;
+   double start, end, elapsed;
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   timer = ecore_timer_add(2.0, _quit_cb, &did);
+   fail_if(timer == NULL);
+
+   start = ecore_time_get();
+   ecore_main_loop_begin();
+   end = ecore_time_get();
+   elapsed = end - start;
+
+   fail_if(did == EINA_FALSE);
+   fail_if(elapsed < 2.0);
+   fail_if(elapsed > 3.0); /* 1 second "error margin" */
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+static int
+_fd_handler_cb(void *data, Ecore_Fd_Handler *handler __UNUSED__)
+{
+   Eina_Bool *val = data;
+   *val = EINA_TRUE;
+   ecore_main_loop_quit();
+   return 0;
+}
+
+START_TEST(ecore_test_ecore_main_loop_fd_handler)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Fd_Handler *fd_handler;
+   int comm[2];
+   int ret;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   ret = pipe(comm);
+   fail_if(ret != 0);
+
+   fd_handler = ecore_main_fd_handler_add
+     (comm[0], ECORE_FD_READ, _fd_handler_cb, &did, NULL, NULL);
+   fail_if(fd_handler == NULL);
+
+   ret = write(comm[1], &did, 1);
+   fail_if(ret != 1);
+
+   ecore_main_loop_begin();
+
+   close(comm[0]);
+   close(comm[1]);
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+static int
+_event_handler_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
+{
+   Eina_Bool *val = data;
+   *val = EINA_TRUE;
+   ecore_main_loop_quit();
+   return 0;
+}
+
+START_TEST(ecore_test_ecore_main_loop_event)
+{
+   Eina_Bool did = EINA_FALSE;
+   Ecore_Event_Handler *handler;
+   Ecore_Event *event;
+   int ret, type;
+
+   ret = ecore_init();
+   fail_if(ret != 1);
+
+   type = ecore_event_type_new();
+   fail_if(type < 1);
+
+   handler = ecore_event_handler_add(type, _event_handler_cb, &did);
+   fail_if(handler == NULL);
+
+   event = ecore_event_add(type, NULL, NULL, NULL);
+   fail_if(event == NULL);
+
+   ecore_main_loop_begin();
+
+   fail_if(did == EINA_FALSE);
+
+   ret = ecore_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+void ecore_test_ecore(TCase *tc)
+{
+   tcase_add_test(tc, ecore_test_ecore_init);
+   tcase_add_test(tc, ecore_test_ecore_main_loop);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_idler);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_idle_enterer);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_idle_exiter);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_timer);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_fd_handler);
+   tcase_add_test(tc, ecore_test_ecore_main_loop_event);
+}
diff --git a/src/tests/ecore_test_ecore_con.c b/src/tests/ecore_test_ecore_con.c
new file mode 100644 (file)
index 0000000..3eba612
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Ecore_Con.h>
+
+#include "ecore_suite.h"
+
+
+START_TEST(ecore_test_ecore_con_init)
+{
+   int ret;
+
+   ret = ecore_con_init();
+   fail_if(ret != 1);
+
+   ret = ecore_con_shutdown();
+   fail_if(ret != 0);
+}
+END_TEST
+
+void ecore_test_ecore_con(TCase *tc)
+{
+   tcase_add_test(tc, ecore_test_ecore_con_init);
+}