From 9cda093342ba5334cf3a2ec854323bc48a7a4eae Mon Sep 17 00:00:00 2001 From: Youmin Ha Date: Tue, 18 May 2010 16:15:55 +0900 Subject: [PATCH] svn update: 48958 (latest:48959) --- AUTHORS | 31 + COPYING | 20 + COPYING-PLAIN | 33 + ChangeLog | 4 + INSTALL | 14 + Makefile.am | 170 + NEWS | 0 README.in | 71 + autogen.sh | 17 + configure.ac | 1514 ++++++++ debian/SVN_REV | 2 + debian/_original/changelog | 11 + debian/_original/compat | 1 + debian/_original/control | 206 ++ debian/_original/copyright | 44 + debian/_original/ecore_config.1 | 54 + debian/_original/libecore-bin.install | 1 + debian/_original/libecore-con-svn-01.install | 1 + debian/_original/libecore-con-svn-01.shlibs | 1 + debian/_original/libecore-config-svn-01.install | 1 + debian/_original/libecore-config-svn-01.shlibs | 1 + debian/_original/libecore-dev.install | 14 + debian/_original/libecore-doc.doc-base | 10 + debian/_original/libecore-evas-svn-01.install | 1 + debian/_original/libecore-evas-svn-01.shlibs | 1 + debian/_original/libecore-fb-svn-01.install | 1 + debian/_original/libecore-fb-svn-01.shlibs | 1 + debian/_original/libecore-file-svn-01.install | 1 + debian/_original/libecore-file-svn-01.shlibs | 1 + debian/_original/libecore-imf-svn-01.install | 2 + debian/_original/libecore-imf-svn-01.shlibs | 2 + debian/_original/libecore-input-svn-01.install | 1 + debian/_original/libecore-input-svn-01.shlibs | 1 + debian/_original/libecore-ipc-svn-01.install | 1 + debian/_original/libecore-ipc-svn-01.shlibs | 1 + debian/_original/libecore-svn-01.install | 1 + debian/_original/libecore-svn-01.shlibs | 1 + debian/_original/libecore-x-svn-01.install | 1 + debian/_original/libecore-x-svn-01.shlibs | 1 + debian/_original/rules | 30 + doc/.cvsignore | 3 + doc/Doxyfile | 138 + doc/Makefile.am | 32 + doc/e.css | 273 ++ doc/ecore.dox.in | 373 ++ doc/foot.html | 18 + doc/head.html | 69 + doc/img/e.png | Bin 0 -> 30052 bytes doc/img/edoxy.css | 486 +++ doc/img/elementary.png | Bin 0 -> 7313 bytes doc/img/foot_bg.png | Bin 0 -> 173 bytes doc/img/head_bg.png | Bin 0 -> 214 bytes doc/img/header_menu_background.png | Bin 0 -> 192 bytes doc/img/header_menu_background_last.png | Bin 0 -> 637 bytes doc/img/header_menu_current_background.png | Bin 0 -> 1200 bytes doc/img/header_menu_unselected_background.png | Bin 0 -> 1596 bytes doc/img/logo.png | Bin 0 -> 3825 bytes doc/img/prog_flow.png | Bin 0 -> 45897 bytes ecore-cocoa.pc.in | 11 + ecore-con.pc.in | 11 + ecore-config.pc.in | 11 + ecore-directfb.pc.in | 11 + ecore-evas.pc.in | 11 + ecore-fb.pc.in | 11 + ecore-file.pc.in | 11 + ecore-imf-evas.pc.in | 11 + ecore-imf.pc.in | 11 + ecore-input-evas.pc.in | 11 + ecore-input.pc.in | 11 + ecore-ipc.pc.in | 11 + ecore-job.pc.in | 11 + ecore-sdl.pc.in | 11 + ecore-win32.pc.in | 12 + ecore-wince.pc.in | 12 + ecore-x.pc.in | 12 + ecore.pc.in | 12 + ecore.spec.in | 231 ++ ecore.supp | 46 + m4/ac_abstract_socket.m4 | 41 + m4/ac_attribute.m4 | 47 + m4/check_x_extension.m4 | 40 + m4/ecore_check_module.m4 | 93 + m4/ecore_check_options.m4 | 319 ++ m4/efl_doxygen.m4 | 97 + m4/efl_path_max.m4 | 36 + m4/efl_pthread.m4 | 130 + m4/efl_tests.m4 | 43 + po/ChangeLog | 0 po/LINGUAS | 2 + po/Makevars | 41 + po/POTFILES.in | 1 + po/cs.po | 170 + po/de.po | 173 + po/el.po | 203 ++ po/fr.po | 206 ++ po/it.po | 203 ++ src/.cvsignore | 2 + src/Makefile.am | 3 + src/bin/.cvsignore | 10 + src/bin/Makefile.am | 37 + src/bin/ecore_config.c | 324 ++ src/lib/.cvsignore | 2 + src/lib/Makefile.am | 20 + src/lib/ecore/.cvsignore | 6 + src/lib/ecore/Ecore.h | 357 ++ src/lib/ecore/Ecore_Getopt.h | 403 +++ src/lib/ecore/Makefile.am | 50 + src/lib/ecore/ecore.c | 417 +++ src/lib/ecore/ecore_anim.c | 237 ++ src/lib/ecore/ecore_app.c | 81 + src/lib/ecore/ecore_events.c | 630 ++++ src/lib/ecore/ecore_exe.c | 1850 ++++++++++ src/lib/ecore/ecore_exe_win32.c | 1012 ++++++ src/lib/ecore/ecore_exe_wince.c | 24 + src/lib/ecore/ecore_getopt.c | 1739 +++++++++ src/lib/ecore/ecore_glib.c | 290 ++ src/lib/ecore/ecore_idle_enterer.c | 171 + src/lib/ecore/ecore_idle_exiter.c | 148 + src/lib/ecore/ecore_idler.c | 154 + src/lib/ecore/ecore_job.c | 110 + src/lib/ecore/ecore_main.c | 1076 ++++++ src/lib/ecore/ecore_pipe.c | 600 ++++ src/lib/ecore/ecore_poll.c | 370 ++ src/lib/ecore/ecore_private.h | 201 ++ src/lib/ecore/ecore_signal.c | 624 ++++ src/lib/ecore/ecore_thread.c | 323 ++ src/lib/ecore/ecore_time.c | 72 + src/lib/ecore/ecore_timer.c | 581 +++ src/lib/ecore_cocoa/Ecore_Cocoa.h | 137 + src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h | 285 ++ src/lib/ecore_cocoa/Makefile.am | 32 + src/lib/ecore_cocoa/ecore_cocoa.m | 280 ++ src/lib/ecore_cocoa/ecore_cocoa_private.h | 13 + src/lib/ecore_cocoa/ecore_cocoa_window.m | 110 + src/lib/ecore_con/.cvsignore | 7 + src/lib/ecore_con/Ecore_Con.h | 241 ++ src/lib/ecore_con/Makefile.am | 42 + src/lib/ecore_con/ecore_con.c | 1698 +++++++++ src/lib/ecore_con/ecore_con_ares.c | 484 +++ src/lib/ecore_con/ecore_con_info.c | 383 ++ src/lib/ecore_con/ecore_con_local.c | 254 ++ src/lib/ecore_con/ecore_con_private.h | 195 + src/lib/ecore_con/ecore_con_ssl.c | 776 ++++ src/lib/ecore_con/ecore_con_url.c | 1302 +++++++ src/lib/ecore_config/.cvsignore | 8 + src/lib/ecore_config/Ecore_Config.h | 312 ++ src/lib/ecore_config/Makefile.am | 65 + src/lib/ecore_config/ecore_config.c | 1873 ++++++++++ src/lib/ecore_config/ecore_config_db.c | 300 ++ src/lib/ecore_config/ecore_config_extra.c | 807 +++++ src/lib/ecore_config/ecore_config_ipc.h | 50 + src/lib/ecore_config/ecore_config_ipc_ecore.c | 388 ++ src/lib/ecore_config/ecore_config_ipc_main.c | 280 ++ src/lib/ecore_config/ecore_config_private.h | 70 + src/lib/ecore_config/ecore_config_storage.c | 180 + src/lib/ecore_config/ecore_config_util.c | 133 + src/lib/ecore_config/ecore_config_util.h | 14 + src/lib/ecore_directfb/.cvsignore | 6 + src/lib/ecore_directfb/Ecore_DirectFB.h | 191 + src/lib/ecore_directfb/Makefile.am | 35 + src/lib/ecore_directfb/ecore_directfb.c | 731 ++++ src/lib/ecore_directfb/ecore_directfb_keys.h | 184 + src/lib/ecore_directfb/ecore_directfb_private.h | 52 + src/lib/ecore_evas/.cvsignore | 6 + src/lib/ecore_evas/Ecore_Evas.h | 358 ++ src/lib/ecore_evas/Makefile.am | 124 + src/lib/ecore_evas/ecore_evas.c | 2860 +++++++++++++++ src/lib/ecore_evas/ecore_evas_buffer.c | 712 ++++ src/lib/ecore_evas/ecore_evas_cocoa.c | 465 +++ src/lib/ecore_evas/ecore_evas_directfb.c | 577 +++ src/lib/ecore_evas/ecore_evas_fb.c | 674 ++++ src/lib/ecore_evas/ecore_evas_private.h | 381 ++ src/lib/ecore_evas/ecore_evas_sdl.c | 512 +++ src/lib/ecore_evas/ecore_evas_util.c | 488 +++ src/lib/ecore_evas/ecore_evas_win32.c | 1266 +++++++ src/lib/ecore_evas/ecore_evas_wince.c | 910 +++++ src/lib/ecore_evas/ecore_evas_x.c | 3764 ++++++++++++++++++++ src/lib/ecore_fb/.cvsignore | 6 + src/lib/ecore_fb/Ecore_Fb.h | 145 + src/lib/ecore_fb/Makefile.am | 35 + src/lib/ecore_fb/ecore_fb.c | 113 + src/lib/ecore_fb/ecore_fb_kbd.c | 305 ++ src/lib/ecore_fb/ecore_fb_keytable.h | 129 + src/lib/ecore_fb/ecore_fb_li.c | 572 +++ src/lib/ecore_fb/ecore_fb_private.h | 82 + src/lib/ecore_fb/ecore_fb_ps2.c | 185 + src/lib/ecore_fb/ecore_fb_ts.c | 316 ++ src/lib/ecore_fb/ecore_fb_vt.c | 290 ++ src/lib/ecore_file/.cvsignore | 6 + src/lib/ecore_file/Ecore_File.h | 130 + src/lib/ecore_file/Makefile.am | 44 + src/lib/ecore_file/ecore_file.c | 941 +++++ src/lib/ecore_file/ecore_file_download.c | 315 ++ src/lib/ecore_file/ecore_file_monitor.c | 146 + src/lib/ecore_file/ecore_file_monitor_inotify.c | 351 ++ src/lib/ecore_file/ecore_file_monitor_poll.c | 343 ++ src/lib/ecore_file/ecore_file_monitor_win32.c | 310 ++ src/lib/ecore_file/ecore_file_path.c | 138 + src/lib/ecore_file/ecore_file_private.h | 126 + src/lib/ecore_imf/.cvsignore | 6 + src/lib/ecore_imf/Ecore_IMF.h | 347 ++ src/lib/ecore_imf/Makefile.am | 30 + src/lib/ecore_imf/ecore_imf.c | 80 + src/lib/ecore_imf/ecore_imf_context.c | 807 +++++ src/lib/ecore_imf/ecore_imf_module.c | 215 ++ src/lib/ecore_imf/ecore_imf_private.h | 65 + src/lib/ecore_imf_evas/.cvsignore | 6 + src/lib/ecore_imf_evas/Ecore_IMF_Evas.h | 53 + src/lib/ecore_imf_evas/Makefile.am | 24 + src/lib/ecore_imf_evas/ecore_imf_evas.c | 263 ++ src/lib/ecore_input/Ecore_Input.h | 229 ++ src/lib/ecore_input/Makefile.am | 27 + src/lib/ecore_input/ecore_input.c | 123 + src/lib/ecore_input/ecore_input_private.h | 37 + src/lib/ecore_input_evas/Ecore_Input_Evas.h | 65 + src/lib/ecore_input_evas/Makefile.am | 32 + src/lib/ecore_input_evas/ecore_input_evas.c | 353 ++ .../ecore_input_evas/ecore_input_evas_private.h | 37 + src/lib/ecore_ipc/.cvsignore | 7 + src/lib/ecore_ipc/Ecore_Ipc.h | 326 ++ src/lib/ecore_ipc/Makefile.am | 31 + src/lib/ecore_ipc/ecore_ipc.c | 1588 +++++++++ src/lib/ecore_ipc/ecore_ipc_private.h | 107 + src/lib/ecore_sdl/.cvsignore | 6 + src/lib/ecore_sdl/Ecore_Sdl.h | 124 + src/lib/ecore_sdl/Ecore_Sdl_Keys.h | 263 ++ src/lib/ecore_sdl/Makefile.am | 33 + src/lib/ecore_sdl/ecore_sdl.c | 315 ++ src/lib/ecore_sdl/ecore_sdl_private.h | 36 + src/lib/ecore_win32/.cvsignore | 6 + src/lib/ecore_win32/Ecore_Win32.h | 400 +++ src/lib/ecore_win32/Makefile.am | 49 + src/lib/ecore_win32/ecore_win32.c | 454 +++ src/lib/ecore_win32/ecore_win32_cursor.c | 133 + src/lib/ecore_win32/ecore_win32_dnd.c | 133 + .../ecore_win32/ecore_win32_dnd_data_object.cpp | 209 ++ src/lib/ecore_win32/ecore_win32_dnd_data_object.h | 49 + .../ecore_win32/ecore_win32_dnd_drop_source.cpp | 92 + src/lib/ecore_win32/ecore_win32_dnd_drop_source.h | 36 + .../ecore_win32/ecore_win32_dnd_drop_target.cpp | 232 ++ src/lib/ecore_win32/ecore_win32_dnd_drop_target.h | 47 + .../ecore_win32/ecore_win32_dnd_enumformatetc.cpp | 157 + .../ecore_win32/ecore_win32_dnd_enumformatetc.h | 50 + src/lib/ecore_win32/ecore_win32_event.c | 1014 ++++++ src/lib/ecore_win32/ecore_win32_private.h | 148 + src/lib/ecore_win32/ecore_win32_window.c | 1217 +++++++ src/lib/ecore_wince/.cvsignore | 4 + src/lib/ecore_wince/Ecore_WinCE.h | 203 ++ src/lib/ecore_wince/Makefile.am | 40 + src/lib/ecore_wince/ecore_wince.c | 363 ++ src/lib/ecore_wince/ecore_wince_event.c | 917 +++++ src/lib/ecore_wince/ecore_wince_private.h | 89 + src/lib/ecore_wince/ecore_wince_window.c | 596 ++++ src/lib/ecore_x/.cvsignore | 6 + src/lib/ecore_x/Ecore_X.h | 1884 ++++++++++ src/lib/ecore_x/Ecore_X_Atoms.h | 254 ++ src/lib/ecore_x/Ecore_X_Cursor.h | 86 + src/lib/ecore_x/Makefile.am | 33 + src/lib/ecore_x/ecore_x_atoms_decl.h | 275 ++ src/lib/ecore_x/xcb/.cvsignore | 6 + src/lib/ecore_x/xcb/Makefile.am | 82 + src/lib/ecore_x/xcb/ecore_xcb.c | 1975 ++++++++++ src/lib/ecore_x/xcb/ecore_xcb_atom.c | 483 +++ src/lib/ecore_x/xcb/ecore_xcb_composite.c | 68 + src/lib/ecore_x/xcb/ecore_xcb_cursor.c | 270 ++ src/lib/ecore_x/xcb/ecore_xcb_damage.c | 138 + src/lib/ecore_x/xcb/ecore_xcb_dnd.c | 773 ++++ src/lib/ecore_x/xcb/ecore_xcb_dpms.c | 451 +++ src/lib/ecore_x/xcb/ecore_xcb_drawable.c | 150 + src/lib/ecore_x/xcb/ecore_xcb_e.c | 29 + src/lib/ecore_x/xcb/ecore_xcb_events.c | 2168 +++++++++++ src/lib/ecore_x/xcb/ecore_xcb_fixes.c | 581 +++ src/lib/ecore_x/xcb/ecore_xcb_gc.c | 48 + src/lib/ecore_x/xcb/ecore_xcb_icccm.c | 1898 ++++++++++ src/lib/ecore_x/xcb/ecore_xcb_mwm.c | 149 + src/lib/ecore_x/xcb/ecore_xcb_netwm.c | 3197 +++++++++++++++++ src/lib/ecore_x/xcb/ecore_xcb_pixmap.c | 117 + src/lib/ecore_x/xcb/ecore_xcb_private.h | 363 ++ src/lib/ecore_x/xcb/ecore_xcb_randr.c | 548 +++ src/lib/ecore_x/xcb/ecore_xcb_region.c | 170 + src/lib/ecore_x/xcb/ecore_xcb_reply.c | 115 + src/lib/ecore_x/xcb/ecore_xcb_screensaver.c | 411 +++ src/lib/ecore_x/xcb/ecore_xcb_selection.c | 1064 ++++++ src/lib/ecore_x/xcb/ecore_xcb_shape.c | 292 ++ src/lib/ecore_x/xcb/ecore_xcb_sync.c | 159 + src/lib/ecore_x/xcb/ecore_xcb_window.c | 2024 +++++++++++ src/lib/ecore_x/xcb/ecore_xcb_window_prop.c | 879 +++++ src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c | 355 ++ src/lib/ecore_x/xcb/ecore_xcb_xinerama.c | 197 + src/lib/ecore_x/xlib/.cvsignore | 6 + src/lib/ecore_x/xlib/Makefile.am | 86 + src/lib/ecore_x/xlib/ecore_x.c | 1722 +++++++++ src/lib/ecore_x/xlib/ecore_x_atoms.c | 324 ++ src/lib/ecore_x/xlib/ecore_x_composite.c | 154 + src/lib/ecore_x/xlib/ecore_x_cursor.c | 238 ++ src/lib/ecore_x/xlib/ecore_x_damage.c | 72 + src/lib/ecore_x/xlib/ecore_x_dnd.c | 608 ++++ src/lib/ecore_x/xlib/ecore_x_dpms.c | 244 ++ src/lib/ecore_x/xlib/ecore_x_drawable.c | 107 + src/lib/ecore_x/xlib/ecore_x_e.c | 860 +++++ src/lib/ecore_x/xlib/ecore_x_error.c | 105 + src/lib/ecore_x/xlib/ecore_x_events.c | 2137 +++++++++++ src/lib/ecore_x/xlib/ecore_x_fixes.c | 293 ++ src/lib/ecore_x/xlib/ecore_x_gc.c | 149 + src/lib/ecore_x/xlib/ecore_x_icccm.c | 1114 ++++++ src/lib/ecore_x/xlib/ecore_x_image.c | 274 ++ src/lib/ecore_x/xlib/ecore_x_mwm.c | 103 + src/lib/ecore_x/xlib/ecore_x_netwm.c | 1624 +++++++++ src/lib/ecore_x/xlib/ecore_x_pixmap.c | 107 + src/lib/ecore_x/xlib/ecore_x_private.h | 308 ++ src/lib/ecore_x/xlib/ecore_x_randr.c | 308 ++ src/lib/ecore_x/xlib/ecore_x_region.c | 143 + src/lib/ecore_x/xlib/ecore_x_screensaver.c | 160 + src/lib/ecore_x/xlib/ecore_x_selection.c | 834 +++++ src/lib/ecore_x/xlib/ecore_x_sync.c | 119 + src/lib/ecore_x/xlib/ecore_x_test.c | 131 + src/lib/ecore_x/xlib/ecore_x_window.c | 1463 ++++++++ src/lib/ecore_x/xlib/ecore_x_window_prop.c | 687 ++++ src/lib/ecore_x/xlib/ecore_x_window_shape.c | 212 ++ src/lib/ecore_x/xlib/ecore_x_xi2.c | 163 + src/lib/ecore_x/xlib/ecore_x_xinerama.c | 68 + src/tests/Makefile.am | 25 + src/tests/ecore_suite.c | 102 + src/tests/ecore_suite.h | 10 + src/tests/ecore_test_ecore.c | 241 ++ src/tests/ecore_test_ecore_con.c | 25 + 326 files changed, 97249 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING-PLAIN create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README.in create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 debian/SVN_REV create mode 100644 debian/_original/changelog create mode 100644 debian/_original/compat create mode 100644 debian/_original/control create mode 100644 debian/_original/copyright create mode 100644 debian/_original/ecore_config.1 create mode 100644 debian/_original/libecore-bin.install create mode 100644 debian/_original/libecore-con-svn-01.install create mode 100644 debian/_original/libecore-con-svn-01.shlibs create mode 100644 debian/_original/libecore-config-svn-01.install create mode 100644 debian/_original/libecore-config-svn-01.shlibs create mode 100644 debian/_original/libecore-dev.install create mode 100644 debian/_original/libecore-doc.doc-base create mode 100644 debian/_original/libecore-evas-svn-01.install create mode 100644 debian/_original/libecore-evas-svn-01.shlibs create mode 100644 debian/_original/libecore-fb-svn-01.install create mode 100644 debian/_original/libecore-fb-svn-01.shlibs create mode 100644 debian/_original/libecore-file-svn-01.install create mode 100644 debian/_original/libecore-file-svn-01.shlibs create mode 100644 debian/_original/libecore-imf-svn-01.install create mode 100644 debian/_original/libecore-imf-svn-01.shlibs create mode 100644 debian/_original/libecore-input-svn-01.install create mode 100644 debian/_original/libecore-input-svn-01.shlibs create mode 100644 debian/_original/libecore-ipc-svn-01.install create mode 100644 debian/_original/libecore-ipc-svn-01.shlibs create mode 100644 debian/_original/libecore-svn-01.install create mode 100644 debian/_original/libecore-svn-01.shlibs create mode 100644 debian/_original/libecore-x-svn-01.install create mode 100644 debian/_original/libecore-x-svn-01.shlibs create mode 100755 debian/_original/rules create mode 100644 doc/.cvsignore create mode 100644 doc/Doxyfile create mode 100644 doc/Makefile.am create mode 100644 doc/e.css create mode 100644 doc/ecore.dox.in create mode 100644 doc/foot.html create mode 100644 doc/head.html create mode 100644 doc/img/e.png create mode 100644 doc/img/edoxy.css create mode 100644 doc/img/elementary.png create mode 100644 doc/img/foot_bg.png create mode 100644 doc/img/head_bg.png create mode 100644 doc/img/header_menu_background.png create mode 100644 doc/img/header_menu_background_last.png create mode 100644 doc/img/header_menu_current_background.png create mode 100644 doc/img/header_menu_unselected_background.png create mode 100644 doc/img/logo.png create mode 100644 doc/img/prog_flow.png create mode 100644 ecore-cocoa.pc.in create mode 100644 ecore-con.pc.in create mode 100644 ecore-config.pc.in create mode 100644 ecore-directfb.pc.in create mode 100644 ecore-evas.pc.in create mode 100644 ecore-fb.pc.in create mode 100644 ecore-file.pc.in create mode 100644 ecore-imf-evas.pc.in create mode 100644 ecore-imf.pc.in create mode 100644 ecore-input-evas.pc.in create mode 100644 ecore-input.pc.in create mode 100644 ecore-ipc.pc.in create mode 100644 ecore-job.pc.in create mode 100644 ecore-sdl.pc.in create mode 100644 ecore-win32.pc.in create mode 100644 ecore-wince.pc.in create mode 100644 ecore-x.pc.in create mode 100644 ecore.pc.in create mode 100644 ecore.spec.in create mode 100644 ecore.supp create mode 100644 m4/ac_abstract_socket.m4 create mode 100644 m4/ac_attribute.m4 create mode 100644 m4/check_x_extension.m4 create mode 100644 m4/ecore_check_module.m4 create mode 100644 m4/ecore_check_options.m4 create mode 100644 m4/efl_doxygen.m4 create mode 100644 m4/efl_path_max.m4 create mode 100644 m4/efl_pthread.m4 create mode 100644 m4/efl_tests.m4 create mode 100644 po/ChangeLog create mode 100644 po/LINGUAS create mode 100644 po/Makevars create mode 100644 po/POTFILES.in create mode 100644 po/cs.po create mode 100644 po/de.po create mode 100644 po/el.po create mode 100644 po/fr.po create mode 100644 po/it.po create mode 100644 src/.cvsignore create mode 100644 src/Makefile.am create mode 100644 src/bin/.cvsignore create mode 100644 src/bin/Makefile.am create mode 100644 src/bin/ecore_config.c create mode 100644 src/lib/.cvsignore create mode 100644 src/lib/Makefile.am create mode 100644 src/lib/ecore/.cvsignore create mode 100644 src/lib/ecore/Ecore.h create mode 100644 src/lib/ecore/Ecore_Getopt.h create mode 100644 src/lib/ecore/Makefile.am create mode 100644 src/lib/ecore/ecore.c create mode 100644 src/lib/ecore/ecore_anim.c create mode 100644 src/lib/ecore/ecore_app.c create mode 100644 src/lib/ecore/ecore_events.c create mode 100644 src/lib/ecore/ecore_exe.c create mode 100644 src/lib/ecore/ecore_exe_win32.c create mode 100644 src/lib/ecore/ecore_exe_wince.c create mode 100644 src/lib/ecore/ecore_getopt.c create mode 100644 src/lib/ecore/ecore_glib.c create mode 100644 src/lib/ecore/ecore_idle_enterer.c create mode 100644 src/lib/ecore/ecore_idle_exiter.c create mode 100644 src/lib/ecore/ecore_idler.c create mode 100644 src/lib/ecore/ecore_job.c create mode 100644 src/lib/ecore/ecore_main.c create mode 100644 src/lib/ecore/ecore_pipe.c create mode 100644 src/lib/ecore/ecore_poll.c create mode 100644 src/lib/ecore/ecore_private.h create mode 100644 src/lib/ecore/ecore_signal.c create mode 100644 src/lib/ecore/ecore_thread.c create mode 100644 src/lib/ecore/ecore_time.c create mode 100644 src/lib/ecore/ecore_timer.c create mode 100644 src/lib/ecore_cocoa/Ecore_Cocoa.h create mode 100644 src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h create mode 100644 src/lib/ecore_cocoa/Makefile.am create mode 100644 src/lib/ecore_cocoa/ecore_cocoa.m create mode 100644 src/lib/ecore_cocoa/ecore_cocoa_private.h create mode 100644 src/lib/ecore_cocoa/ecore_cocoa_window.m create mode 100644 src/lib/ecore_con/.cvsignore create mode 100644 src/lib/ecore_con/Ecore_Con.h create mode 100644 src/lib/ecore_con/Makefile.am create mode 100644 src/lib/ecore_con/ecore_con.c create mode 100644 src/lib/ecore_con/ecore_con_ares.c create mode 100644 src/lib/ecore_con/ecore_con_info.c create mode 100644 src/lib/ecore_con/ecore_con_local.c create mode 100644 src/lib/ecore_con/ecore_con_private.h create mode 100644 src/lib/ecore_con/ecore_con_ssl.c create mode 100644 src/lib/ecore_con/ecore_con_url.c create mode 100644 src/lib/ecore_config/.cvsignore create mode 100644 src/lib/ecore_config/Ecore_Config.h create mode 100644 src/lib/ecore_config/Makefile.am create mode 100644 src/lib/ecore_config/ecore_config.c create mode 100644 src/lib/ecore_config/ecore_config_db.c create mode 100644 src/lib/ecore_config/ecore_config_extra.c create mode 100644 src/lib/ecore_config/ecore_config_ipc.h create mode 100644 src/lib/ecore_config/ecore_config_ipc_ecore.c create mode 100644 src/lib/ecore_config/ecore_config_ipc_main.c create mode 100644 src/lib/ecore_config/ecore_config_private.h create mode 100644 src/lib/ecore_config/ecore_config_storage.c create mode 100644 src/lib/ecore_config/ecore_config_util.c create mode 100644 src/lib/ecore_config/ecore_config_util.h create mode 100644 src/lib/ecore_directfb/.cvsignore create mode 100644 src/lib/ecore_directfb/Ecore_DirectFB.h create mode 100644 src/lib/ecore_directfb/Makefile.am create mode 100644 src/lib/ecore_directfb/ecore_directfb.c create mode 100644 src/lib/ecore_directfb/ecore_directfb_keys.h create mode 100644 src/lib/ecore_directfb/ecore_directfb_private.h create mode 100644 src/lib/ecore_evas/.cvsignore create mode 100644 src/lib/ecore_evas/Ecore_Evas.h create mode 100644 src/lib/ecore_evas/Makefile.am create mode 100644 src/lib/ecore_evas/ecore_evas.c create mode 100644 src/lib/ecore_evas/ecore_evas_buffer.c create mode 100644 src/lib/ecore_evas/ecore_evas_cocoa.c create mode 100644 src/lib/ecore_evas/ecore_evas_directfb.c create mode 100644 src/lib/ecore_evas/ecore_evas_fb.c create mode 100644 src/lib/ecore_evas/ecore_evas_private.h create mode 100644 src/lib/ecore_evas/ecore_evas_sdl.c create mode 100644 src/lib/ecore_evas/ecore_evas_util.c create mode 100644 src/lib/ecore_evas/ecore_evas_win32.c create mode 100644 src/lib/ecore_evas/ecore_evas_wince.c create mode 100644 src/lib/ecore_evas/ecore_evas_x.c create mode 100644 src/lib/ecore_fb/.cvsignore create mode 100644 src/lib/ecore_fb/Ecore_Fb.h create mode 100644 src/lib/ecore_fb/Makefile.am create mode 100644 src/lib/ecore_fb/ecore_fb.c create mode 100644 src/lib/ecore_fb/ecore_fb_kbd.c create mode 100644 src/lib/ecore_fb/ecore_fb_keytable.h create mode 100644 src/lib/ecore_fb/ecore_fb_li.c create mode 100644 src/lib/ecore_fb/ecore_fb_private.h create mode 100644 src/lib/ecore_fb/ecore_fb_ps2.c create mode 100644 src/lib/ecore_fb/ecore_fb_ts.c create mode 100644 src/lib/ecore_fb/ecore_fb_vt.c create mode 100644 src/lib/ecore_file/.cvsignore create mode 100644 src/lib/ecore_file/Ecore_File.h create mode 100644 src/lib/ecore_file/Makefile.am create mode 100644 src/lib/ecore_file/ecore_file.c create mode 100644 src/lib/ecore_file/ecore_file_download.c create mode 100644 src/lib/ecore_file/ecore_file_monitor.c create mode 100644 src/lib/ecore_file/ecore_file_monitor_inotify.c create mode 100644 src/lib/ecore_file/ecore_file_monitor_poll.c create mode 100644 src/lib/ecore_file/ecore_file_monitor_win32.c create mode 100644 src/lib/ecore_file/ecore_file_path.c create mode 100644 src/lib/ecore_file/ecore_file_private.h create mode 100644 src/lib/ecore_imf/.cvsignore create mode 100644 src/lib/ecore_imf/Ecore_IMF.h create mode 100644 src/lib/ecore_imf/Makefile.am create mode 100644 src/lib/ecore_imf/ecore_imf.c create mode 100644 src/lib/ecore_imf/ecore_imf_context.c create mode 100644 src/lib/ecore_imf/ecore_imf_module.c create mode 100644 src/lib/ecore_imf/ecore_imf_private.h create mode 100644 src/lib/ecore_imf_evas/.cvsignore create mode 100644 src/lib/ecore_imf_evas/Ecore_IMF_Evas.h create mode 100644 src/lib/ecore_imf_evas/Makefile.am create mode 100644 src/lib/ecore_imf_evas/ecore_imf_evas.c create mode 100644 src/lib/ecore_input/Ecore_Input.h create mode 100644 src/lib/ecore_input/Makefile.am create mode 100644 src/lib/ecore_input/ecore_input.c create mode 100644 src/lib/ecore_input/ecore_input_private.h create mode 100644 src/lib/ecore_input_evas/Ecore_Input_Evas.h create mode 100644 src/lib/ecore_input_evas/Makefile.am create mode 100644 src/lib/ecore_input_evas/ecore_input_evas.c create mode 100644 src/lib/ecore_input_evas/ecore_input_evas_private.h create mode 100644 src/lib/ecore_ipc/.cvsignore create mode 100644 src/lib/ecore_ipc/Ecore_Ipc.h create mode 100644 src/lib/ecore_ipc/Makefile.am create mode 100644 src/lib/ecore_ipc/ecore_ipc.c create mode 100644 src/lib/ecore_ipc/ecore_ipc_private.h create mode 100644 src/lib/ecore_sdl/.cvsignore create mode 100644 src/lib/ecore_sdl/Ecore_Sdl.h create mode 100644 src/lib/ecore_sdl/Ecore_Sdl_Keys.h create mode 100644 src/lib/ecore_sdl/Makefile.am create mode 100644 src/lib/ecore_sdl/ecore_sdl.c create mode 100644 src/lib/ecore_sdl/ecore_sdl_private.h create mode 100644 src/lib/ecore_win32/.cvsignore create mode 100644 src/lib/ecore_win32/Ecore_Win32.h create mode 100644 src/lib/ecore_win32/Makefile.am create mode 100644 src/lib/ecore_win32/ecore_win32.c create mode 100644 src/lib/ecore_win32/ecore_win32_cursor.c create mode 100755 src/lib/ecore_win32/ecore_win32_dnd.c create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_data_object.h create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_drop_source.h create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_drop_target.h create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp create mode 100644 src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h create mode 100644 src/lib/ecore_win32/ecore_win32_event.c create mode 100644 src/lib/ecore_win32/ecore_win32_private.h create mode 100644 src/lib/ecore_win32/ecore_win32_window.c create mode 100644 src/lib/ecore_wince/.cvsignore create mode 100644 src/lib/ecore_wince/Ecore_WinCE.h create mode 100644 src/lib/ecore_wince/Makefile.am create mode 100644 src/lib/ecore_wince/ecore_wince.c create mode 100644 src/lib/ecore_wince/ecore_wince_event.c create mode 100644 src/lib/ecore_wince/ecore_wince_private.h create mode 100644 src/lib/ecore_wince/ecore_wince_window.c create mode 100644 src/lib/ecore_x/.cvsignore create mode 100644 src/lib/ecore_x/Ecore_X.h create mode 100644 src/lib/ecore_x/Ecore_X_Atoms.h create mode 100644 src/lib/ecore_x/Ecore_X_Cursor.h create mode 100644 src/lib/ecore_x/Makefile.am create mode 100644 src/lib/ecore_x/ecore_x_atoms_decl.h create mode 100644 src/lib/ecore_x/xcb/.cvsignore create mode 100644 src/lib/ecore_x/xcb/Makefile.am create mode 100644 src/lib/ecore_x/xcb/ecore_xcb.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_atom.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_composite.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_cursor.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_damage.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_dnd.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_dpms.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_drawable.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_e.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_events.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_fixes.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_gc.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_icccm.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_mwm.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_netwm.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_pixmap.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_private.h create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_randr.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_region.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_reply.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_screensaver.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_selection.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_shape.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_sync.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_window.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_window_prop.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_xinerama.c create mode 100644 src/lib/ecore_x/xlib/.cvsignore create mode 100644 src/lib/ecore_x/xlib/Makefile.am create mode 100644 src/lib/ecore_x/xlib/ecore_x.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_atoms.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_composite.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_cursor.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_damage.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_dnd.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_dpms.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_drawable.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_e.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_error.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_events.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_fixes.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_gc.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_icccm.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_image.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_mwm.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_netwm.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_pixmap.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_private.h create mode 100644 src/lib/ecore_x/xlib/ecore_x_randr.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_region.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_screensaver.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_selection.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_sync.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_test.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_window.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_window_prop.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_window_shape.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_xi2.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_xinerama.c create mode 100644 src/tests/Makefile.am create mode 100644 src/tests/ecore_suite.c create mode 100644 src/tests/ecore_suite.h create mode 100644 src/tests/ecore_test_ecore.c create mode 100644 src/tests/ecore_test_ecore_con.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..4acdbfb --- /dev/null +++ b/AUTHORS @@ -0,0 +1,31 @@ +The Rasterman +Tom Gilbert +Burra +Chris Ross +Term +Tilman Sauerbeck +Ibukun Olumuyiwa +Yuri +Nicholas Curran +Howell Tam +Nathan Ingersoll +Andrew Elcock +Kim Woelders +Sebastian Dransfeld +Simon Poole +Jorge Luis Zapata Muga +dan sinclair +Michael 'Mickey' Lauer +David 'onefang' Seikel +Hisham 'CodeWarrior' Mardam Bey +Brian 'rephorm' Mattern +Tim Horton +Arnaud de Turckheim 'quarium' +Matt Barclay +Peter Wehrfritz +Albin "Lutin" Tonnerre +Vincent Torri +Lars Munch +Andre Dieb +Mathieu Taillefumier +Rui Miguel Silva Seabra diff --git a/COPYING b/COPYING new file mode 100644 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 index 0000000..376875e --- /dev/null +++ b/COPYING-PLAIN @@ -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 diff --git a/ChangeLog b/ChangeLog new file mode 100644 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 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 index 0000000..bbd57ee --- /dev/null +++ b/Makefile.am @@ -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 index 0000000..e69de29 diff --git a/README.in b/README.in new file mode 100644 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 index 0000000..0a59462 --- /dev/null +++ b/autogen.sh @@ -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 index 0000000..23813d4 --- /dev/null +++ b/configure.ac @@ -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="" +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 + ] + ) + 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 header file.]) + AC_DEFINE(HAVE_SYS_MMAN_H, 1, [Define to 1 if you have the header file.]) + AC_DEFINE(HAVE_SYS_TIME_H, 1, [Define to 1 if you have the 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 index 0000000..4cc07a7 --- /dev/null +++ b/debian/SVN_REV @@ -0,0 +1,2 @@ +Revision 48959 +Last Changed Rev 48958 diff --git a/debian/_original/changelog b/debian/_original/changelog new file mode 100644 index 0000000..659787f --- /dev/null +++ b/debian/_original/changelog @@ -0,0 +1,11 @@ +ecore (0.9.9.060+svnYYYYMMDD-1) unstable; urgency=low + + * New version + + -- quaker Thu, 22 Apr 2009 18:12:06 +0100 + +ecore (0.9.9.050+svnYYYYMMDD-1) unstable; urgency=low + + * Clean up changelog + + -- quaker Tue, 21 Apr 2009 19:14:37 +0100 diff --git a/debian/_original/compat b/debian/_original/compat new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/debian/_original/compat @@ -0,0 +1 @@ +6 diff --git a/debian/_original/control b/debian/_original/control new file mode 100644 index 0000000..2f0169f --- /dev/null +++ b/debian/_original/control @@ -0,0 +1,206 @@ +Source: ecore +Section: libs +Priority: optional +Maintainer: Debian Pkg-e Team +Uploaders: Albin Tonnerre , Niv Sardi , + Xavier Oswald , Jan Lübbe +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 index 0000000..57d5703 --- /dev/null +++ b/debian/_original/copyright @@ -0,0 +1,44 @@ +This package was debianized by Debian Pkg-e Team +Sat, 07 Jul 2007 09:29:10 +0000. + +It was downloaded from http://download.enlightenment.org/ + +Upstream Authors: + + Enlightenment team + +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 + + src/lib/ecore/ecore_value.c: Copyright (C) 2001 + Christopher Rosendahl + Nathan Ingersoll + 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 index 0000000..ea857f4 --- /dev/null +++ b/debian/_original/ecore_config.1 @@ -0,0 +1,54 @@ +.\"Created with GNOME Manpages Editor Wizard +.\"http://gmanedit.sourceforge.net +.\"Sergio Rua +.\" +.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 +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 index 0000000..088dd41 --- /dev/null +++ b/debian/_original/libecore-bin.install @@ -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 index 0000000..4e6f99e --- /dev/null +++ b/debian/_original/libecore-con-svn-01.install @@ -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 index 0000000..d5353f3 --- /dev/null +++ b/debian/_original/libecore-con-svn-01.shlibs @@ -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 index 0000000..d497998 --- /dev/null +++ b/debian/_original/libecore-config-svn-01.install @@ -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 index 0000000..ec0e971 --- /dev/null +++ b/debian/_original/libecore-config-svn-01.shlibs @@ -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 index 0000000..279e512 --- /dev/null +++ b/debian/_original/libecore-dev.install @@ -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 index 0000000..9ab7e32 --- /dev/null +++ b/debian/_original/libecore-doc.doc-base @@ -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 index 0000000..ceb9f01 --- /dev/null +++ b/debian/_original/libecore-evas-svn-01.install @@ -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 index 0000000..92c2b6d --- /dev/null +++ b/debian/_original/libecore-evas-svn-01.shlibs @@ -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 index 0000000..72ceee2 --- /dev/null +++ b/debian/_original/libecore-fb-svn-01.install @@ -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 index 0000000..2593f16 --- /dev/null +++ b/debian/_original/libecore-fb-svn-01.shlibs @@ -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 index 0000000..a115a75 --- /dev/null +++ b/debian/_original/libecore-file-svn-01.install @@ -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 index 0000000..868a4f6 --- /dev/null +++ b/debian/_original/libecore-file-svn-01.shlibs @@ -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 index 0000000..8da8885 --- /dev/null +++ b/debian/_original/libecore-imf-svn-01.install @@ -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 index 0000000..15aeb84 --- /dev/null +++ b/debian/_original/libecore-imf-svn-01.shlibs @@ -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 index 0000000..34d8efb --- /dev/null +++ b/debian/_original/libecore-input-svn-01.install @@ -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 index 0000000..b95c6bb --- /dev/null +++ b/debian/_original/libecore-input-svn-01.shlibs @@ -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 index 0000000..e118708 --- /dev/null +++ b/debian/_original/libecore-ipc-svn-01.install @@ -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 index 0000000..6a9ae5a --- /dev/null +++ b/debian/_original/libecore-ipc-svn-01.shlibs @@ -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 index 0000000..22c55a3 --- /dev/null +++ b/debian/_original/libecore-svn-01.install @@ -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 index 0000000..43565e1 --- /dev/null +++ b/debian/_original/libecore-svn-01.shlibs @@ -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 index 0000000..8c8007e --- /dev/null +++ b/debian/_original/libecore-x-svn-01.install @@ -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 index 0000000..b5a9660 --- /dev/null +++ b/debian/_original/libecore-x-svn-01.shlibs @@ -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 index 0000000..a9861f0 --- /dev/null +++ b/debian/_original/rules @@ -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 index 0000000..cc370ed --- /dev/null +++ b/doc/.cvsignore @@ -0,0 +1,3 @@ +html +latex +man diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..f898c07 --- /dev/null +++ b/doc/Doxyfile @@ -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 index 0000000..0ea8777 --- /dev/null +++ b/doc/Makefile.am @@ -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 index 0000000..2dd6b44 --- /dev/null +++ b/doc/e.css @@ -0,0 +1,273 @@ +/* + Author: + Andres Blanc + DaveMDS Andreoli + + 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 index 0000000..d75a8ee --- /dev/null +++ b/doc/ecore.dox.in @@ -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 +@author Tom Gilbert +@author Burra +@author Chris Ross +@author Term +@author Tilman Sauerbeck +@author Nathan Ingersoll +@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 + +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_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 index 0000000..d43cf8f --- /dev/null +++ b/doc/foot.html @@ -0,0 +1,18 @@ + +
+ + + + + + + + + + + diff --git a/doc/head.html b/doc/head.html new file mode 100644 index 0000000..2c61795 --- /dev/null +++ b/doc/head.html @@ -0,0 +1,69 @@ + + + $title + + + + + + + + + + + + + + +
+ + + +
+
diff --git a/doc/img/e.png b/doc/img/e.png new file mode 100644 index 0000000000000000000000000000000000000000..d42aeb420098578b19a3eab3d6d1e6e73e3277bc GIT binary patch literal 30052 zcmXtA1z1&0x88Ik9RgAUhmiV^M(OTu=@JkSNr59J-Q6kOARS7BNF&|dDWSj}|L3_V zDkz-Ud(T?ytua(pSq2C5DJBF#IC8R*>frYz@IHW!3PA`y{;&)10m6HA8F8rcC*>aa z0M$%EMiP4b_amphC?0$U!%0@}Jp^G9{(DD&(lW@vC(&Hxl%&vpVLd?;K!}OKo`WD7 zNKR5r(_{Y7$NeLb)~`o*tFMfv@iC~Mo{PdoLogU}Wn~J2=`cfx_Gm)Z>0wf$wsaxr z{zS}}@{?n1n#}4_1%bwiF@Zelyy^DYxA!&fap{9U7(d+zkN$aBzWume*IM_V`?1LN z;`^T>#ITib2|J84OWjP$8M7)KZxNgz&CLX#Plo0{wuX~05Q=>t@2`&_VMdj#MM^jt zL=6c}H1#>~=~U<^iZ2`Dh+f_Qxi;{9xZSDm{`>?h+xKp-6PJ>o20|C~IL(2&;(1Dw z4rsButpEHz5{9Qi-w~!FqN7iow}yx>ZZCGI5sHy=`n*rtukqnI;03V?KC?m6l$~A+ zUmcRf0#I+?t#tU1LEDomuiN{bDRq;2LkXFnobB_i;S-@uWz8yMDv0-$*QE_TRAt&7 ze6`r-dEt&dU6=MWQu_LKC;Oe}&8g}8nq089=$rfNl`4c)tC6%1NjsjwJD&WR%527M z{FfDt%kug)W#U8Wgzs)==WXXokSW$V`QS3c_g? zr|Ea2qDhRR$EqJ`0bQWhyhd9nBXauCjekwVnK8Y24(5u(!8&g5!u!jyabvwVJpb-;FFq+g9;s{^GrSkEY+8T4 zwbx8cU44R%nmU`mXi|@rot=FZEck zmcqUsi6=R);HIt;oAwwq*zg?fG6kM(xg||0ZWdfoJopSZPM9@z`_E~p1qn}BSQwc+ ztP46t97FFiN$vZ-YfT0<^t_gkka(k=gJM_fxS)Y!luV8zyqoKKFr%bO6Gr*TnGkXK zZu99&+~6|?_~9WcFCs+C$S9prY&VfgMCt{Ddu@*5LQ$=@rvlKO^G2T~6oP#ERLSe* zRD?E~YM1k(MA772s;YL>Uuz}~LxdbuI2Gg-=XOqxA;K3UE#Pln1N}s5Qh3^|WL1d? zS9FPv%_xM*5mu2`pTN<^u)A>1RT0FZ?OopBLKJ&75}`p{7B;-xZ-WY$f{@4D&Z#9{ z4f_-iN<8Iu{Yvyyxc6*IF(o%fL+RBAD5Y`Pi#6r%sHTODAas}Z^6dDER%WHY+H&prC*i;#q3>P*&%4wcjvZrn4guRW{S^eXS1(x3{(V>r@&0 zI4-w&Cd-+Zqf-Z)lD!kd)Ag4*+?y;q$rf^tBK9njE%nSo8@=!V1!#xmpR?up${Va9 zStj}!6>b-u+xYv50=X|79XE6q`%@*+nk--kpmcNo1eM!}x_StXT=b%2|H07fK}XlVY{}+MZzTDq|y3QR7bE`?L@HQ?~2r?>Yp+x?Xzxy*VSzP-dF{ z>hPAD*FJ?qk4mb`oRr;gx6R{>4wO(7l~C#9Y4?*s@9X0&n+|4l#IN>q1n4v-U2ue7 zpm+!f2tFcgPDFaTf@Q%s_$gm~mDt${s9F_W8BxSC;}I)k>~lCo-`@b&NQMKD^3lye`$2nk*6T ztX$teV>!jr_qp+Ue_6g$%nx0T!F;4SOr7NmN-*IzPsCv ztzsel+99fd`g6!eJ|#f4uLNOrveHOM;b5jBa-#2tBn+eEP3MCbB(lhpfYBALs0|~J z4SSaNDFg8v2Q3fJB@FHec_Hj7r5s_Mot^ndN2`eVBTNq}?iX@u;Ikh+F?k_o^2y(l z>a0$?LSF?P^@jNjIjT!srsYItGsFbi7%UR)nKU_fsnBGP?`DqryCauU^<-@mH7wsi zb_2#ip&6@EgJ$P$ALWhuh0Vw<M19zU-wyWp{Z^h)MsaVn@7tPck>IL|Z3mpXie4i=l=GeR8@b~3xsP%5|O5E8Tu zwSlf2@4C^46C1b-c`!YHz8M=8KDLR7gfw?PB)6_Ub~0DD;|gYol-}~`lKTq7d&gc?a7#V4tWWCwlExz!AMwM9 zEi-p_chfmK|GKzCQDCAlfZ=#591W%hDl|Zv+dqJwtF8dH zx_UqVw#qUj(^QYdpN7bOxviODE>1Vg`?wk2;qzx%Q9&U-Q$A7}2@EMq(45lcn0$h9 zsqQF-Ydg$#ki|sh<>ebU`lBBi86sTpF80RrWrAmEgH5Z!r0;{cA>Eyk^y|%`MAn!v zeHRTmKgQ?Jk?|>Ub|;HQiEGS-N4r;6{EoLr(qA)n@@aW$%IdaPI@Mr5=aMmE zWx&{R1BR&*vY3aY6Rg_vV!M$n*mNsLa~XGgbJMj2bfFK>w3)eiRR~p?Q7bQKKiJ6c zJoRs`F>!E46y)Xe7Rr%mA|u2lQY^I~t^EA_=;Y+WajG)CIz|A7@FdC3kOnIdkUwWK zBv3s(JOmLi7k!aLV`YzGkt7LabV;qF%u9wuPcJT7<&gJPQy&91FX>S8XkaZ|G&Cj@ zrp)q`;u5;5FnFINd~stR9np*T==GM z(eh#4l^c`06*9qr-zJcB;nI+cVu>SHA&&9BTc#{2DOrhlCere`d##!xvai&tuGwVr zi;^$yXC%qNJ>=7_g#~X>W8-B#?m}Vsl|@dT1zn7{XH%?6`@pX7pl9OYSvQ7rB;qME zxq}k-5-;Kzp4uDHV;uTXMm(=Qv3Xt?t;h!I3Yk3ixT=8~>!)L3XgJiVpO8lt-$oGK z9UaLjGK44ZcuHIjAN%DM@vq1*X}(ZXNeMxVB6J=J9Xmsxq`HI+b@agn*ad16%NOhV6ogqKbi<>{lcnK ziJpL3whv&cRIKcioS~6)zW3jZ7svDSy>qjF*%0q^O2w zKR=7J23oi{#LW0RAU3IP3rg$?FQ zM-oU`vIfoKii^I4rogcKBVM8XdC#>4Re03=boHB9UWo%}_yPb2{mu(JDYa;D&P8o0JIfaO}J*U|ljmC#Pa&E3ob{3( zfR27uJd3aInK#9(e~m{%;#TMP_^<>O@BB!8f14luDhx6Kz$I!YhE^hO`)B4`8jU@Z z=jn*utpMt$*w|-ee>|5XgQjEYWgY}Q&!0=Yb?H%I@CmF3jW%F||3}(OR!X=JfKRMf zUOw-#cFw?JgHDCB6)c(wj$wA-O1gu6);2c&bLtHv{s5hVp(X3WPg$EeI5Hw~fA#Cl zC{L>5dSCJtc%$Sp>%mk}8HEXioC!zM%S6?;x$aGDsO3xh?5(YhUxagX6f2k8YL`@o zqvTv)UEvH24kAEpx7+D{<5c*s!FZmJv$>LFo|cot&iigWT5F%^zU;XZVc3uROqk3a z>?Nk|V4Od0pe~jMafg{@2s8t6J(bgVn5XS|lXu4eW|esal+ZeqYXDP}lMH)bE}k*6 zLZ@o^LQYPOln)H^V=%S3)zar!l+t)?mqAO6oQQImt)@*tj|fUQ)GF1WgzihV%Hja% z*idrcJ*et*6f=y8fNrS${+|5=)320;)+_s!&kcC9%bP%fubi%R`xOa&`E_sxcHAvN zvCtyR^4-;ejyOfr+h3J4ZmlB3qQ04eA3kRJJ=}WB%d$`ZoT@bP?guoM5r3JSAMnK$ z+s*5Xi}XkE4PN9VI+i0B@tkx%`nL3%eewX)DWhiLXb(E4r>74{=dpE(eps>R4S0AV z@@}z-%L&|&U+6zAL_AJc>F3Q^1O#r8YR~lqG_cTe!ld&(Ra_+iGWm>4wXgi!CnP-l zkHRJFJwK&X_PTrPlJRBwt9Q$7dvkeGSmtJC>vL06Q)s59ri4_uGUN9h9UU^yUi)US z(FrQNtGl~CdCVQLVtp#5uRl-VFYyylcgvQ55F)dQ70{S323jM2RT>>wH|U$z&6(8A z;gOSj2J&i-XR4=%hT+B!CWv1M4mea* zXqPo&_wF#a=4S32%0Qh-@Bch6^`(3Mi&}vX*I!eaQ8n(rr7%@in#z~agLA=6!LVmQ z3emh7{?H+-)2rU@9`a0l3cp|s&X3OO$%rG$;=J!IR-(b1KEels?Z!?mh%K_K?w`_; zXe7ceZNvRVwW%~vql(eHE2I`-qlA<{pnhZ9^CBtQ&GD?DNKVdiU_fZ z#s_fSvTC+b+(9}{!a;FEWcQHu73K>?G;yROm-B>p9xLQAWpRnswKdbiuS=Fx>vRM3 zWAY4R2iPXaA67ihI}r8HEg16aV=2xd?7S6qU0rnO>)6;>4YBGDKd1^Jg5ttBEf(=3 zn$*PO`YGnJ-)beAu@b@9&9bh$k8u);iSi79McOhIzKqQ>F4L~?qFa9LcBrdnz9FHx zJnkg$MyBm0(=aRTam!XHbaar__6iH7<;EoUa0d8$|Nsz1HM(m z&&NvZz#Lbcs5u^;XEwuCLt5pJdMm2v+5r9CJUV)T^eS6S9V5{)C$&ub%+^rDt;&Ps(O%MF{k(`Qp!35%Lv zTDop3xV+(mD(q&;1!D0Am;+&aj2gP>u0x{e9-)~LWFebKU0~KUM67Bc!>a*n{EI8< zaZu5SY}T+ZzKF6hINbYRmf;Cv&OMNSxW(EO2Xo#c*_d#WNou6??Ug4dkkkg+h0AMD zamBx+p{cxG59iocI}XNy(Df^{(Q$E?`TQO}9-vWwjNy5|tw;}l1#kvw?$t9>0gAyB zlXIcCAJR01^E0xA1k!mlk&I6QV@9ENV-CDwO@|>%XFffmJe0R0p0-p&M>K(=3*tPU z>qA(K9zWy&?YWr3+h&m#w!z4ohf$Y4pCHHb+N_naMqp1=imk7X@e{eMS~I~C(vYv6?L?og z(KUSwE*0~_GebpZF;-s{j;<#vI%H5da>$;Jh=r1}-4Y35G?}SC3uh6RPpFX>6i>H7 zVIY)g{`!t+vnOgI9UY<9nT=NtjdH54EpFt-R)}FBgh_c{P=)y#C3LODPYZu}Ii#XllykDjZ77bgI~; z|1|wF_EvgSF$j8;Q~2)y6^{j)2Yl&-;iGsxiwl87m9?~VaOwcASE@G;bh!i6MtSn! zC4`0v_@FjjPE$+_-Uxss;)9Turi_$w`QXsd-5D4d%3q)_dCEA3xEF#1tI|lCuK43V zcY8$@65`^5>Z6lzeEQQV0Q&w!BJy0EAd}=fk=UY8i+J_)_VxL;0$h0p!!6_BniX=@T=>0dh9>U zS!#bkPC)+gt1)VI!)kFqSxzI+MINHut8rNPN;EzT1ObkJZNLXY2P4p!RlB^2em`l% z>b;Ay^3Nd9`Qrg>e7KlzcuNj++-m)b2>puS#>PfGeEi(VkPsV6e0==3oMifYS9fGd zmI7jUr<;TE0RRM1Vu+FnxLEv9;ApRZgMF4RBpv~>hXJ?Z{pDv&NJ_6%5|}!kfB2VxgE}mVPIgay!JeojKM#Zq&wt#J5$~O zzEL|_@F)2~e;Ra8Kot(kwactdmfPPRFE*R!_Sk+R%Si!DrqO3BQO61e6?NwE&q-%& zdO9nrcap7@TG=!@I=ZNnQ}qSd&O03scL#I8FKFdpg8xk6+E5Dbjnk;mZ|HdS>Xma) zP>>Ywk^71dUxIxgTf)~CWJN|`UHEPEMGF0}`j5lfN&@JtRaO-SjSt3n$c#)(*8M;^SSgHfU-$U|=7QN9 z&#lCKfbATbtVgpt84QTTFm&ypG$5e`eYKt3=I(bc)~oyC1TK%^HK20y1qILFM?VuW z(*T-1yHQI518<)*Wh-F5J}Ozlq1;a+3*q#nMd$U~%1?D&qS%3qbhGxEdRed0amlzP z)bIY_jRCMJE}r%~i-TT}4yf>7EGQQ+rD|O^ze?SjJc@?c0>0?lT*dmgd0D1p(Tyv< ze-K`p_ySL3O}k7>F{-QMdfEHkbg`PbJkTqfp$*(RFdZ_pL^IHYfwq$;hglVIZoj1LikByCu=*N$L*#f?e zHh#`Ba~wgW(jLg?9sy#`E4eWWENDboP6<1F=aa}TRHhZJx`7h2sffp ze_}r~Xms=edoCXPt(8u>t}{$Ppc!0fFq^3k-Ea90bfDXB{M%8y);}|vWt{C^%;9_d zYgwI6lshN53qWfR2ZRSjokh`F>XQ_bJfGE%lsQ{l+mohzB>-b7+`yI`hV41Q04Vkh?FB*X6D*QNN=Ng2%qA;L1PQ+Er$lj-I~8W;~B3&-JU8 z1^L9K{4a35_{v4^Q-u&8hB-QW)a*Q2q2-m8mG?sl%yOV8UL*@M^j6mj8*FZJKsG?5 zSqGh6DBSp!#mU|@=yv(o-8V3V3a|>@dK)zw%Vc*^+8m>nW^IJA{VT7P-$x6tpKDt; zZ}o%m#FK=WfCK&Kyxv0$dbZC96`X~zt^i(U(8%8L=eV`Htxfp9FeH>R(CpS=!?nKh zdD4oCKSqF~kyp_ZE5^m0&X|$~T8DzNqT-ZnbC$i+86F$uRn|KQAO@*U1Y~g>dPxzD+6ufB~iOnpk<#9x*iHL}R zP#6cJ%D73*&VD=t(hJ|WEk1kN#yubZ^Z@5VaiD)9wjg3i>#YkGQQIV9hgvrHYx)k3&*TnQ< z{hxyyUvJKU`|jPlo7-E<9DX7-qD`BH6k<_RK>R$^JW0vP1>WS3*FO|-DR^a?raVB) zQqKEW>2vlE0UJ%*!lU#;LKJ2$3j3)}VtAG6U(HbAIqC$Gk<$6ehBD{p=O(=A?=%dE z=T%`X()#Fqp-&a>!H`>izVZP8#%w0U%38Q(-CS5(ja0NfFjdRT*@D$yTtFFofPi9# zzJd98czOnH@9eC^6#L|;*G|N!n#@V$k5ARl*-zY4sxWV51g;tk%PdB&%b-ENrqBHexX{R@+-wB?HDe#g@HSc z9AOhzWRnxsPU~-59GbSkfBjj+?LB&YY#|)pdyZ!*$rpZ}_zeDOqbWHnaKKZ3w(X#PJeg6n?Fg5&;9RuI2INb>%lW7Lp@*eJ<3sRsLs+tjOsrt*ao^YrCCtZtpHEYwZJN z1SmRwI0Ftx;Rf(&wA8pGbu2v=stGLL#9Hc$ukb)tNFER5%eR<@KjF=ihc&YOdG)c| zvP^9-I29dP(Q{=QPEIE)7ngJOeTKv}+#XqEtHd76ie!XEG^bnkQ6Ky8fBxDmtLpHISieE}ZA&Q;R$T_ba1p?^#KX>%X?*WG z9uMd0CPP0Kejd*El8}v;!jhY#BLO}xMqM{Z!U}9k23L;z5r{mX zh4)V2vHNXd#z)cp=L1?xwk+pXhkW5Y+NyU`+t-CIV!WvU*~{;Kci8CYvr0*CFqj0y zl}o)nJSc-$r3WODPZtJU-NCkK;7(VTz>q7Bz_;L*)v zR5nF>8pg_)d{fX81w3^XOn1$WC0LJB2WLqTlHa_TMo7_|ygpNs>6Sula%5GEO0LP>_%ibB}qR0!NebD$Vt34D}7-cS%((i0oIk|TziAvk2N2KS9_T*XHHIQcC$}9Eo zKxjZU;0MZ;14;PSGO*eSxw*NO)#jm+>{1%F+f#_FLYrb1I4-Zi;t#z*5QIg@?a)U2 zVL`s>nQl@Lm;@HQ>F;4@GMlb$&@dQX9~BuV!xO$r-Z?TYB7Ygc_(=I748ON3W{X@} zl`rFCl~_ITOWBxAQ6AJax=4BjuXtn$W2W>ivhO^barUodX8(!|`dzJtEn+e_eC{Tm zWtNnbv}e>0-iJkfBK*V3-Y7vNmMo-~5R1B;X-{vIb%~7*X|g1iR&=k;it!hc9nl|? zlOt-5pX=+G-CM3T30J*i!X_y2*tY{I};&SsR9rE!uy3Y-1cG`Szl=R;*?c(VlFQ1*oiMu^vt~EpD|{i{!JS`1h7ysmpHCL5Cy%Kr z*j=UZU6c$Xnc(>my5%Lx3Q88&Kh9mFRmFOlAx-J%oK0;ekLDX1 zw9BqIVAh^297lf|k;;lCs03ZdSWJ{+&**u1-2x@=HRyKRfV*%6QbX&if?8s+`!*wK zFA2feBDAcolAO8+wbuH#(Rn7X;s=0)Rr#|lib#@5ib~7O%*@{dF$nWQn&qR-=u4O& z;21yNuY!U{F&iosXFitvQ>db@9`^y1jL6`-3Q43g)EuKGCsU15>c`)^f4HxVr1PE6 zth0S)P#KVZDm-rje4Y%{)-$_oSys|%Utiy&2x)q-wNV)YegP%nUj*m(<{;q+cnPJr zLVY^jzrCbygoEUjW7HU{VVxt~wiCcLbMNi%r;dZ6?;$w%{Q9pA7@w}=2>39&vguM* z7_5s4crkP+#dHfRfTt>_j97tQT~Y5)lL-_F9}hq}GPxJk-LM4&{4{Z^qo`k_LW;7o z=vdcM>}1d(z?P{2Xitt~pmG~dt2%PVcnn}SJ!)Z=gU9sy<AYu zWBALg26^6|_vX(ZG`R)T9AN9^`-zHnCB!qS__9lk%9kSteCvYXRqqV9rh0Z~YY36x zo|n7$z(iWmG8>C=p=amgyDkUKOAr_*zlqwJ^_6dLZ>#6*S3Nt9KU4e8CZfs?C%w=K zD@iYdiUF953h4Pa^YoQ#uTq%HtYn`NYu zY=h!VAoMgq%IHhu3;97%Ali+Tgd`8R@vR2+Hu$m#5eI;bM}Ge<&QFOuYtIXaixpvs z_%{&2a6iDr!U{iEGN{mIGi*Ao1w_}=!@~xc@lM?q+|Fjl2RS)84+K;xZa}19($LVD z?wQorjzY>Y)6;GMeZ9W<{m!#ebR%;X2!;#a-yP5ItLnI8u>%U(Ac496Q+TC$e-tes z4u9e;^=|I&%)rd8xIUb_AceLU-gS!T7Ro2WfY0YDc!Yw2LJD@RigCxs+tGtxRZOow z-l%e>Dn?B11%gbHe?R~}6_t??BO~L`% zz7Pgibs-Z$hW{zfm`kdqnvh9(akk~d+ZDhqjb-HC)XJ-|k|H<&I@b;|7haQQHIm@^ zghIXWvEZJ6Z)&v4`(hFkgJ>m!Gk_6#oqc_>vH}3by9(VJvrC{DWvh~qeD*hs_5=U+ zV)XT68}=&Zcyk%##5Roie*1@~EwCZ`UEaUHo+(z_pc2Ddb>i>35N0D8HXpDSS_gMG zCM6|hw*erVR$^jZE#lt#L{^=wsyCglUW4dXPjz**ST-=a@a?vNQl0~xLaAK0XzJGw zzJR>e0mmx#i3ytgFF|v)mOdh)6pSbE9nWXrb?0zRSo@t1LEyl#x2K0~i~nbMV9#y7 zMVPa6p?b+b;Yn?7ES+qe-n5z8&3SUG4FAxRiDbFlOkk#g&v|aqf zU<{4y zxsuG=e{KE8NbdWo{V0vvy{_IpPZWz~ncs88{C8DiQ0Gjk*6Uk02coY1YcYX}xA1f-T@Jd1NdqKXre7y2Hqz;K=g0Dl2Ci`oDQ z{|h4+Q1*LtLn|?K?|?a2wIm=4zStPD)e9e z0sN#N#2+7!Et{MW@q%$EX1)T6d0}szLm`>nAt5X40huAwKHLQ4Yy;f{GaYY0Gv-ya zLytua4`4;p-uU&#@BRn)WyznYiv*^T@D%PlUvJxrgDSz+&G{Dy$*okcegERVR4A{i zs`3T3`R32;WJ=C%d+x^pUbc!Zl z5+EZ0H@i4;{Sre;oBqj@CyrqJ{E3f?`}^uj+gXHsfZtAh7!$=nlTHuLZ-1;l_e_F-57up6Aq0 zBflhNXH!$+_Gf~xQWgX{2u_k^GZ5=4^}v3osK@jGiOCTr#gu9dMFrL61lBE)MN5Ia zDqEhXQxyh$maAQ#sLHk9szKTy(qWgX_{IO9gro)>Y2kn9*3HA?rT_?8U=$sK;KVVI zfwFR3xAA%tRHX=Nl#4Dhz!O?=b>N8FhynBq)P2K+&8H8*c3!czu;9^_$IkDh%J9Ik%@6B^p%Ek~JCX+}zyT z&imgBDw20ozzFL?!6Gr__x{bM5zEleiEYnopbv=Y&wq>E0mrVWRpzk>sqo09|7xYhO?lfw4DKs38Iz+>I1WVon6?{*{U|wE07e$6a z^&&TT4@~yakdP2^?Cxq}IZ>eg)_s=vjC({w@Blu$&(U`JeGuS*Uwo;GW`RM(+|ELx zbGLOokSnkogj+zJd7K5Go}QM12*`0ZkYr(`_>Bukwm{XVSJ%*}Q$6&yORlyy?n{F0 zv@n;t^2El*Hh|W2PTcRjyoEpl@c==!4@|_3-s`r@2?Zq3f7{6!meN@g2udXdg{Y~i zpAgJ-?Sat;M*6Y5Ko+7j2H0IsJ;4rsOXRfxTi4U(2`HzOeQyuVgNSa2C!k8D=L8Qx zSv~}+;%}kN`>3uiQAXh2QZpDa4jUop{~R$u5^V*+yjE~dVQk2h&}YQ1;nggd_;3Ab zQW)wOBV{bocpdgvKxpIl+S-~DXy@wjrev9e7I%L@#?c+@>S!b&KKlH)Xv-Pn8#hqp zbJ-ji(XaUGt4H=Pp8@!_8n^{$#g;lO{cof$^;~VuUP4R2i)vhIeqW@aN0tcM(scCe zhbHCkMmB<75oBEJiC}QO7#tnF76iK`LwU>NG9`s9FgSP}xI4on?1oL~3{)-($Y0#| zCM->Whc#8pZwW?Sjm2Qxso}4DJI~0JYT-!%JR%C=cM(lR#EM|DUeGAaO0- z4oaZ^_u*W(@LO$OF+99y&p`k3GXb(~m4+7=zR5FSV#NXjVkMD5UAJO}3y6yk2n=;k zwa|4L=+*%&IrDXNJmzs99<||ls0Tr$Ib_u!qMQ^E1v7CF6Z@@SJHaMR5%K2Dv{2-Vq|(84EIyg3SXc%fATKX) z!mLfXX!3F+`ZaDc0#U2W){sVMXedDB=AotEFR#P0@*II1X4vVQc?7;FowA>*)9=w2 zGm;#ne6E2?PcIOKrQ!8XULF&O@w@k613r@?*LpqlL*t(%HmIkkN8Lid3mha3g{+<4 zLwmC+!Bzkr;{P>B)g+cLY=> zD{1g zIzR}3I_;8)#VMIC(69MPH2TJ$?UR^y7Ac>~YN7#)T1{?J%a% z3(lvJpxN}da!0v2a)qOGp&%n8{{=^R3Lyr>QF~tMd}s@T!{JaiNb&KpjJlMSYlJa? z)FC(o~h|#$876wIphQ=r-#lVoU#iXk`O>+pszgL zFROAK92{hJuBsOoxHk~AY1Y6Hl|KqQ0i#VHXNY|t*`yUH^|Xa&U?PGOGG!JYhlhID z5{;{<5HV8ETc3iSXMBZsAy8bUO}A8$DK0MO#Hs=Ey&f-DgV^NI*^_Etc8 zm|m58ea5jyH%j)CQY03zqm3*UOBOl0K~{Z^{Jmf%jE!ya#kfnDcm@*u9vqa?I9_i5 zQyOA<%(3{Bm?ySln?Rb>(K)m4XY!iGfr{QLkblqggu zmYWC5>dbXbgiw3QpErZOiv~tzW?o+2wk=QESK^o6T2sP|?k`@vzya$L1Emw)Bd4US z{LtOsFEay~ai_+_#^NIdJq6LTHwwX~AEhuv=;@JwKMWb(nt$~1iOtOPG04LuNmSzv z{fzAg-~&1Ecuhf`{_ZOs#ZD1I+@;{?#VH5_g1DAE$sgc59j&wH=Hx(N9W;gY5CjlV zX#{;n&ZbL`m#3%J$ml4?G=AB17?{)O{;Dtpl8PC;=c2A4d$rv8@z$ju73b-XNgE!A z2iwCuKW{IunNO^BhHBZB#_grENxf!gs&RD|Mp4LO=&FmJtrL3k6U`!3|WkU(-@IYz4a9 z5u!n#$8G-p!@L|&3YJcA0Rf@d+y6GFz7va3;>si`b`n3yTecdKSVe$?EFUpK($rjJ zvR+sr991W&e&4B3$~2o8CNBeI2W}SCq=YFE*5pQR2^)=1>3xt6YHlqwsG&{BrB$60 zD6W_l8?jzck?32^hSfAAlicc6NrR5EH7yttDdN^&bLr*dD!>`t$0q2Fj#K>+u}2Rw zmS8~Bvun`LaeZpu$(>{>4JIEV)C$vKZen#~Eh^$rYAwJhDTKU{b#Tiy5>eQ)b~G&i zG6^P&t&S%BGH6CO!oVDU2ErJ?z_90FcxXdBBOTeUTa`b)z{z@rQUlxn7%_4C%=rCv z1Tc$mFn!PD1&BPdb{^d(b9kPX36n9(CKYOl4=WNSF?>s$KKfAyg`1MaBdfB(2e^~g z7#QyQSjL}z?mlZ*5AgK#9JArcR6WCcS%NLiG&`D%_bBdfDWT?e=gN@QPy*!fR%TI@ zgbl9$hVY$ft;o+mv2tj!Ep9FVKhTlIaBt_bSoF6P!@~2hx(}1hQmhOkw;+bV!HGSI z-?hhmtQ5dnWr}B^-Z;!KN-A`WM5FczqsxS|%Z6trkkz@4SS9u)Nuh-F6oHK3-PE^4 zQ-|)!G46nG5OA#g5gX|?7a-qY*7pPsuEYs8BuXEjFgE~htyX2+e&q2rZ)V~;ba;Y| z-Yf+Y4rHaa3)$FoaWspywqI-m=hyxO+#F= zZ+kJfdfD`C>SI$CK3w+!Xq^}y9X(oX0UsRaF2jEDpSr)jI*NdmpIwHd5yKq!Y%@-; zmKR#$)eJacI#>rF=iDP+R{p z-Ey$OK~8-=I%`i5bTRMj?DX?%I;U-s>%?q~sGw}Hm(UR3mP*L4;e`CDD6)IOKv z`Atpy2yjmGz6c_sWaCpYXR9+*C@sdfk=~lMDemysKNe13t3IS<)MeDK30;EOJi0ei zkq!=SV4bgjl`Kouie2&pIr>0wmi7zKa__Z>c0}1#@;FH#9iY<<0Q5z53r^pmfV4J& z189<%#>U1KB^9vDJz-WpBnr82I^i?r&Q7z#4o&MJHDoHpf};JRPB>rPTr) zTI(N+d_hM?CwOpmSN(5eEOq*I+Hl5-074oBg4W|my~oI|1DKhj*-tPq$bs-0KLkA2t-RUdoBZ`(9gbueZYnF zt3n6jO+PXpdAh*mN~u~}^k|*W7`!v0nV%KS^DRZvIr>is;qo0Z?WL4%;pAT2ATJ$e zr3Pnr|d08Rq$pdllpgA+H4GD()+c@IZozpaxV@v5~6zaNL1={QsYdXx(8AOmz7 zRFqwy~8IW zR`3Z6`bal`9f(l;?*w#mR|Ys#jLwp{4>L^6?6I5+*i8-ot`(MBi;y6h;I_0@$~f&0 zfpfTCRc+_;uS(>#T>l||pL4$#O{HaHy~(BcUj9O+JXaBwa}?&glF^RnR{SasJxgRRm7dfNzbUS$;Qo*B%7G^+#`jT5(`TqroKnBIw^DX)b%x>kVX~b5g^g z*Y@0A?D(o~Q5&U-AVPEtGH=~LAqZqpNJ7rz_lpWPx$^?T8xaY~3_kKV$;kBF@@+SH zKW#JfBX$#msWOHC?#lo!ssnPLI=UE|{9UpOh_O9di&Oo77U0vk4KgGQl!1_l2p*sp z`Qm@Wv=vmgwNn(B?94H_(*elL8RV3FJohFFrS=LzIBwUl!A=V&fz79oPT|lV)Zi#U zfbJ55Eu?Jnf2{b6-_|nw2!z@N%^W#lcmE?IuVX8CV83q&wJ1wjv`YUWUCFv>0XG~EsRR8b3k3claW&DawZJ#{ce-?t{_g z(p?tf4HAmdAUX5|^qRM@qvhuf7>rsbe~BleC$&i^3Ln2r7IFe~|3uX=JyB+lPQuLK z&F~Kv)kEg{+#i0Fmi%0Uia9s!ts_Dw!p0hWga}chxzC zNApaGVFBaQ{wT-hpBLnJgX%&EDj0G(7mNH5TOya!tmPe>CU5no@HHj(;k4)or2}zZ zem`WATOiUh>HXX%{{$bQBW<_H2B}=?ykpv;6O(*ykk)(8^(T2?-oqfI0K&rd@5-d)XxNdu1k5ME~z(9-7swX{8x(GZ2;#iX%Kh$N94`zP;sF)+``>A4z& zR9l7?KZJ4w1t12(@N@!L`Q;oj!iQNtLt1H9YRbqiq&%vQX&@ab2gKYkcJd^Q9Tk2TxY%doMtW`slsy;yhLf`i$xqT6TiJrR|C;8krqGg!N+Dt? zHp)CdezXf&YA9&xEC#=AobR@R6<{PMJ~2 zWm7gA=%#IGx9e3dqX~8rA7>mJub=WenLJ5gpB_vYCt-DX3%Z9!dwaV8OlazX+DvOk z%!U26QmFY}7)RPAaEj6ZvoxM6hC)=+uGiK zwLe?4aR;=(KZ7(V2G1-&YFy$aKsaMSm+u2X)iKA?Eoo(_6kJ4Le_tQ_v|Yna?xEx+ zZmN8jInc@PT&k}h-{C7Hp@242-V02NJ{QXVK^n4y;GjfN+$2j5-~*y|p7l{=*RYkT zi?Yx8pKTg{_~#K4c4jtlnfFaOPXqG*$iMA--2NZr2 zShvSLN(WT6rJ#e^f`Ei1N*WrPkBIQAhupWA&5&Oo=c$NpE-j6qjctXXG#_T)4AY~i zoJADa|E@9Z@9ljED4;L&eCGtYT%LuC1>x^V;0pIaQB4(SdE zK6dzNBZdJ0IyNjE`F<->;T-Tp(It~!=eVSr)m5tt_*#dEW!JJCr_lf7{4lWgGk8Qqbf-X_>lNvK%*{=*IOSDL zL+uwrss4tB+cRWkWi`?6OwRIKraj{pms5*nC|U0ET9Ug4RR!;&x?{~|H{g=#GNgUH zlSXV_z5xU18Niw)%BqQEH$?C{W@rB)56kqpftc><>N1(Cw5_)6j%MM_8E)G~}1 z9vmF>238_HEhUBE|3g&3`t}AO`Fmth(L5fx$V{|LY*8VSy6?x2AAxFG=qiCGAK!G*6?0)q4O(VX3n z#KAdmp;UW$dd~0t`-f@}mzJgnZNRqLOJ*yZCvt0u)nH*k-!UwXChK&Xb)Qa-kFPp{T~H5m-sRHf=AR$X!)&^|mHO1pUME*dhT#qcf;SG; z!OX^10wDHfX+c5399+KwK2ghUOD6Bi_)Db60TX{>;ma0~{s13gojAzwiu#G4paRZlkcbWcriB(BL#bN9Bk zwP8|(vw*FDYp)4-tcL(|Qy_kTOebWxE4{GeuXU?<)QPylEy;x9?DBc1im&pqRJa+j(w0%gabDddbq!Dw>&qe3D#uZ{9o3h z&;llczJ(5xK~7%Yy%EIj7k|MIp01Fy`$mK&_wOhmvYlY{*oFsU9_V@3QP$oMydJF2 zp`1g}vMqu(u{Z<9k0y;tmiJc<54dZ87HG8=fLf#vsLqgtgfRjb7=3@OH5@?#RU~lC zzuqLt4tC{YWP(TLA9{ISf#g%{K1)4z;YhNbAoT}`Dmm*^O%cAZ7f!)uUs;NKXeX;M z!MWnS(qFCko<;T_H?a&j=SB(XBx+vj>FGJ}@|INT7mdys@oR(2QxLd%9L8qg2_|^JOD_(f;#hsmmcDvP7VfTpOZkrCCxjym&*^9}$O1U2K`{w( z=`2(nXAs(ySz%AXfb3NXf3t`_3{edt6_oIfz z_*YX0D4l9Qy1O;QzYGI&gih-iv@Cy0O|&34ak;fcbR?v={kt~u=TGXNYYkz=Z`Ow7 zw>LL8Pk;n?ks!o~?@Zb^qzx>kH>7-B8G(XuXyeDPUpLkA%fYI4Fa<@~9*6)9(x*i# zph&s^2zdYAz+MoDU!Hw~MVI7bJGjP#k(n)z*;V?MT zbnb&h$KKHJcg^hVY=V3GSXdWxI&3iO!EE_WC~~Wle}??EEc&bmuYiHsR|mDasMl$Q z5nfA=z^VX%t&QduKf+A`VM>GQk%(BJF8S_`L3V{8R z547S{a1zHPEopA>6ShGkW#w_SMLPw4_iw=ay#&r(>n>DP;P6P+HBs1ZxijRFJ)Go) zzt%`dND$J}(vCDQlvGt4PeC2CAq|dmKTyA#!+Dd7$5ZMH@I@PlEv654ch}nZ2-)H~ ztSEZ+8uoynXsfdS<3ak*$y^QF#TergsPZ0Hf?Ftj!{zM|XrL&6H@+Q1x)YxY+$e1S zy9R4(2g%d2PZ&*s4O6Tm?GoOJ0#ln|Gr$6;8DAegHm-szKs z|Bj`KWoi%n&DgozZ+|$Q$s2u)x&-x5i=D6;Xyxo)yjbagjcqptM{Wohyw)GzDCR(b@8LZR^&`Zv zueWloCz-D$jMzwC3_n&c3ihG?tS%ozBf7G(k}_IsboTSjn9cjd?(FOg54!hrYU*t0 z6>LI5bFa==Jtup6`$hOW-th?u)!*vtr`$kFaJjs^Opfkk{TVu)&5#rSwzhhblauelSC`U$^5njpGY|CIo0!BBj!`S_E3hr;MBH{v zF#UdqZ-4so<;$u#d`K}=h9cKmLrozeA*Sm?i!yioR-OH=8)WjZ_;!Wb_#Od!r>~z} zpPfDb2Rx#Uj<6Qh{7X|v<^9RIbjkX_w|JlKL%ugWYFFP>rx57e$Khgffh1dkxUFAz zDF`G*L~zqr+zUreAyKLEFyq@?T46jLEs379U!`^g7NZaqiWw{Pq7 zva(tn?mxrRz$U2LeIDZ1%p$3tEQkjf(UN+qNa+Q!&vDy52q@6?f7FUO`|8yzGx*J& zz(Fe&q=^|7E0FD~!c>Get&)R5u{gCE-)nLB_wU~+bQZ|~zZktP$96jL_m7!m!Sne` z$e+L|swPYOT!v6bvZk9DMB~p7TrBbWOgt~2XegV>Lux>u#lgj8;N5$-T4LEzgcY6$ zc!)B6ZxXH7)5LNaqR4R{p)!y%Ha46fc*nUqtZtG#17Pv0!@m0MBmEaBRG2B$$q$N( ziazv#mha{#HeJR5Og@`}h!E=7ZgZ)EBl+tS@8xe|IhEq1;`j=4ajhpqo8bL%&}!bC z_}%8#*5xL&UC*9Bjn~#rQ&U&}z`@IVW#R38SqEf)G5CoWX+oRD@z6X&hTW_yl!d2=MFwOcRyF z(s=w#sfwss2tvZJF;c9mYPagve~ym29J@B1{ZY5EwLQbF5|}jMvuZkO+`iysWnC5? zlwvjRT-X(~1Cd^QON*>{*P9pPCNks^H?*%CdZ!=5i0H0qX}MfTCO?RPEDf~iYMsAu zuV3G2<%CYs$Dn0IPdN4(=z(ez}sE@p! z`3K9^Pq+6wW6)w_Hni&c=@w7bJ(_IVbU{E@`K+q(LCS3uu4)M2j}VVTCTAW+v;JaKJFam_2VaKqge z7Z*R0Q&N_E2oLAVWk-pplMy0{8xQr}8mHR^B=&xMn4FqY6zYTInPGH%sU%oCxPUsx z~uOD9UXlF65Fr6LWVQC zJm#nVh+lE<&NH<~RhXm|<>aU+@9OWrET8bCY~$mf^N%nuW9Q(QQ_qmP=z%UjLpO7t zd+wE#wnospl`j5&|0zB|OC94p;CpY`TUpiQ6&7-_^I;>%rTO@Fs?|aN;tob3Qb#M%FNts;UrLY&7=+=7kmbvd~_rE{X8y;>rg9v4_|#-+`5Yv2}=t{JDO>^i8(W zm>A4PMY`){6Ly;~U%q^n4q*Ha=v|1O=;{iK(hy~Y@y3};9HNt77EsE{^kJc)PwzxV z<1%*@UP$ur5J3v+CTIpP`$3C6iII4-l_(dlnvw)}(YWrc0u10s7eM=5ZMTQs6dc$y z8`^hEcdf3hY~1N)%h)h~s;l3qrdqRK&WXkmtRZMYFD)U#RS_1pjgb*898y>zZAdMK zSv?gZXx>0U1pFJ03TsSZW#z#SU>atQ&t|T^m3;bS{RnAQfzez+CT|T%Z_6OUy-GDr zTs85_mFtExMo9_J6*N=N&{8yj93Rl;rUE z@h@H=AIgX?S#CB4x-m%O~yda9Ra=~Bfu|m z($dmOVb}O+xJfbZ1Y!yZ5lF0Ey%wVd`S}fc`k5oR#S*0e(lh~%U-CnqX$i|)i2{V~ zGl?)vu_ot5nwdsI$B-!c%Ce7ux8Z9xfQHvDFIdMNKT!w~Ws;f|4fXc)NL_-y@#e>o z%K+>cw?j9HN{~7>mOyF(+@2qC_;SCXY$$<|?J6cU)zEWiRu*;=KXMs`P!Ce1yli(w+)E$4o^_sad;(fJ0B z0K`LCS=k2~A*aVR&IyB7?XYbPs_iBOn)35sL^ZSc<4}@g6tExXd)Xd%G?q3roDa~_ z((XY5Kr2Svz)E3ZLBY6)h{$;OpcnP|-;7^^eP2MF+zFNUbO7cJ4b+8PCv_>w>f08r ze2s$SXw0|$siJ_g(Suel*U<69?vA?fF6J0Wn6@KBLr-LDlFd9lB|u=xW&C!tazr@g z<-1uf!X6^3uo8`8qV?^Xh4 `kPGGuU|L4CGI8lY!k$3V<(&mZ=vuiQ_1>{KXa9cXfFTd%-}Uu3 z=-eu?G_^6^Cr_T_E>CT&t{w|WNlh0FT3K=!#q57+KLSvztG}P;b**8@T?%EkSc8~A z`O-&ghD?7UUgx&d=aP~Pmh~eF?Hc@ny#REmoHu+F!TA|mXsiv^F~s_vuK^fAC+akh zC6sQrjnXWVvAaiBOMnOq4<8&J-d{&&qq!fu8pmq!NFuzPoOXSHPnVwyRE2PcJ1`c{ zL*q|LlCCb}9*!4)Z4(|Io}ik@HS$_mG7Jc*+n^A{f%fp520x|-Pr|w#46xM* zs({9C%oc<&rR{>^wyvnCNUh_kdJsOh7IVO;m7oF-B(%IzRaGrZbXCOoF!TaCJs%yN zkzRa(xUTv&0O!Xi%3oaV!bbfMMIc*usdu@JqHU4TtGu#xaL5Pi0mb3b(N$x9ekVrI zG6!_5ATbjy7+a_0ES0RBsn9Rdc5yjuhs#PUlj-x_h{B83kF;WdFH;VlSUNK7RT*N9 z!&_t1)0g)kpS5Lm%YBGWuHx64dDHQHcoFQ25(xHkiBx#ZKI1;;zkCczSO#&wk467Y(R6D5`Sa%uoSQy?UOTKGc!aCv z_hOSc)%xD-KYEB9aMR$+7zlyXSGh)G2T+BI5(H6`N@aWq4-FlJII;DI$hc$UoI!>= zcd`phOLqfN!)*mwcrENG%%9MJ~90wVXMj+`)c|?pTO*7FLUi2o075K zXAN#nl)jB*@@s(XJG>7Ktxd^WJN}B9$CE?iBf4QU)O251xYbU$#DZ#B-T$5e^$l@S zoL_(bc>OftlaRZ^>=$^Po=*2MFK_yh<}hpeO0FKsTeg2K2<0MH_Uk4X1A9tC{ste&9B8yq7P6QBv|E z55Dz*8FJ!@s6R66+{aG%HbSL#IoUR^qOx+tj@J&BFP^OwJq#6Z@L7SQbEfg*F#rT;m&!@*A^BCv8%UzwL#&aRd(j| z4g>qGa6QNP1(BxXJPkU+Ha`23vBLN+h8F>`c21thFJ4)@|ELk9vd6OH?yb|;*FQuY zN99=qyng=R{lZojJ12}ae1w?Ed5Zlgyy}nTT2%O1lLYN=%$|;JSDs69_zC_b;ojr+ z6Z%g-I9MoflB!f=>vns{orVt>Fp9i)^uo$_%)KyR#IU9z9GKwMVPi z{M{+FK0kj26LE&syMG69I}rO!pE#s#Fzlre7{il+uk(>KeK%- zrnC7oElhatNj`JglCjF23-p#rN(>w!9^sSk61Fk_6in-LGPDpmqQL4}w2Ri3PQwzY zMwB(-Z6_dV&eml>Zbu6OP8MGz`3d9>}I@X9-4;;yFjx?B3}?v2uE>W2Mjm;Ou{D}B=Zx~FP>KE%38+RPm|9T1Crrb zYp96P)rs^9`l#(>ePDLI(}^P3^jl{cH|-r!d1#npdzWnHMYb?vUyXgov~&LHL~2$@ z=4o?{OZ-0Km<^C}yiTKY=(u71rYK$@&7_nDBV0O9r_ddikH^$C9K@4M#vUfrQo#)7&J2QKJ^gJXPh)k=F4}+#d)`i`ZNF5GT)me`cqVVyD3EjR z-{_lNALQ~#3_L6uQN-YEqTmY3IuV4spQl26(5|;Ydsupa#fG8zgC@f z)DVQoigGbisSM2Eq$4Okx%<-duXp}$KnyK3h#=C-G`L`g!o)pZwvmB+BG}@(eX#Z6+zD^Zw8yc#;Cb2Q-WaU5Bwd#Q09`zK$%uC zZamkS5O{BWdfHeFkZ9e6-Zwp)F4ZKguC;p4zjDVc_L}PidhyDxCg5M*skb9Hr&}1Y zbH(0?;&X6!56GPSh=s3;6MHs0h|mul2y0F9f?E^^6ogT7UVTV#a6if7mlA42=crvQ z_lWCS^<;5@3bH#hjJTKgu!tOmBA;Lj7wFE*j2uyMcHAiqE5|TMrDLt(1GF(0*qj)+ zTSw32XQ_$%v{Y9Uw8~tuqAYwmSP2ow_k1ZWVta1mS7P|9UuE;x-7JuGUPYc0HK#gm ze>WG%f}*zqop-nq&yzHNzJX`h^`aVl%%!-ru|}wW-$t`%o1_eFPpH0MLwGZGY4e2I zItZ@}k0+?buE6@GC<)=cKr6r*D zyp?3aqLVz^d>b!VyIMu#$<5KuSUlCC)YwJ7Qu3FYHLlPvs7-7hLjD(}^z-Ve6u2ck zhD)>fSOW3Q7>%-J$~WM5xj#Q75&dqkbLD_2QErw)^${qUy?BtRYr|Q$?@1>^>wEiQ z=DVB-pEqyb#H!^RXzJ^GIDi5_r){p_A{oK0$7IL;py^mrbI0den|*F7zyFWxv-ud+ zyCm%7-GpS?%_apF5s!-IUy~*&^NK!4p0gTe8H=H9jgE5t^E4 zfI6#6eeh660TvnunHf!;D|_87;=IR(up%wu+6!BrEy~i ziX0>GwCBE(vN&2J60wjm2}or&jgn3z+554_u;)9#;yw%{-;XhFuZQek=WZ>hw9 zJN`2;arar8NeA>1YY5?>M`ZyR6X2UYhDf>`FuI>t0y2)U$Y8o6_wWATJSg}QZD{F- zCVLCG$gxd`y@NNTdLbRfhHfT@~05t0&m!OC;_uwXDVhGrh)2hI*IPr$ZH;Yc?46y)XQr{U)_ z7cx%OU9y?(T6jVN^VtoVnR5*k+mqRo0Qq91?pdCmb&Bu>1-7Q*yd~2~R zZ$ulZLNH!hVvn+8CkT#deCBhb3LXSsu6_B4jZtb!imlh-#0v+<`af^*TTjW6qwMjC z85vDHY-}sJ(pM(~ne6yLa|VytT%g~BK#Us`t$Rl9Aa%3(CN6)l)G(OOBLSFU0BHeC zQ5Vpf$DuPNT_6rSho;kuabrk>{kHX==g38Kb8|8taA4X)b^Py-{QwOWl?gn*do+?B z+Liqco`C!^val@80`Fn(=hMd*y;H)daZmIs!w3pMWgk6l?fqGRU2m0)g+tyR+EykG z^Yk8O;Mg6@-{xQbyBz@lkkc>K`!A>Q&j@qNb+4^ne$q9iqYNyWpPw&rKq>bHQ(HJ?Ph(9Mmi7+qVZNCPJa{ z6QOzUq-vSQXNmz1c3a@PbU8mh>n6yLDo8x9Br}W!f5H~L>cQJ-vFk<=^y6oZFm$xp zR94q4Wth@lB!T_JjH`Bae^Wps-wV##<1ZycQ>& zzn5(-#=*n0H37@>3Br>H`HoKJ^VeF3YZ?qjW;uiJVC5fz8~YD8v#lY8_-Fy1tza?> zq~z6~o}CF{tQTI}!3Zvo5RD3d9HC+f{&nee5vO@fDD3I?r`;ANK7al!+3Na8?Wz9p zc?#lNxR2kDB|b%Z-}^`ju0$+7|BLq+G7tmU4}|E2K|nwN2W!k)*MQIE9yz`M71LYY zdweuKo=m|8UEn0W{J!>Diq$GwHXt1ThV~f3?L&3}M*7MJOgB=Q%81EFdndWK_?cqr z4n_^=w>CE$uRsgJM;%!M|Ihlh_80w5j%QPLRh<4ZDCOclL?VU>dGOxSrOu}$@@9L4 z1D`b6w~zT0^V z3~1icRsu<10f~VHnFr>;ZveBn5ne`yQAH5l%0na~J(U?YpLL$<8Jh-dVLDRzKD2pp zN3Ww1F%E>ZEgI!D2gS@9IAyJ@FW#DnV4WA&Z#ko_!^#cD4rxDBT1asHhM5_!Z>1n+ z#}EQo{ew4g4Yf%!lQ9{vn?tDnBxv+mw#E#P!i4Y^02z8|myN`sJ5xw)bO@oVSQ<3J zx0&wT5isHz6Q}8%FxQU268P`41wPr!DwD(!Lu|x9({XoC)OhNfh*9<%+LVaoGDd$Vw zZszpk(h!hmc%xfY1?Xzh(5v^lQVTH!>Xd@vU;4y_wucjUk{;)NJXx^$+H80 zyG3l#K2?t2?jJqoz)xH9tk!vn78YzRPeS+_IATnJt5fg6a^0O?KuQqK5`B8d_x8{Z zf)UO?7Z$F|ACI{((E7D{$NnJk)Y!s_GWZewljlBX&kYs4_!qA{JWkmF!EnMT2u4VR z%{`}KmVG9sd2v%+qICUJetM5n{U0WAC*UplQu?+)BULsZKrA)B4bdo};wfL5lyp`L z7=)9CaLpUp;;iP$3Pjmz+=?$otG`w5-<~=C9*K#G$q&TqLx4qa4c_jwTq}j7yVktC zJYhVM#bB*nseJr-WeNn~@;d+;NP}L3o^(|2)1sd~Ypsp#%zp%LDy96H_sVVX3bhdi zICvWKuB@QD@CFCE76eUUIMN4Wj$2{)B;2oCM*fsOpCg_@GuRTPEz9g!8e}hoQwHu4 zmN!8GNX{;J>rgX?Q_}HV)cDC0*W`s7`?+M4I5}?C<>M%sXv{DSl9Z$*Q8QpfUjgo% z1P%T%O&eb+4551l`ufY|+{!;N&8ctz+UfeWcoTV!}Zo!!s|-;TzhyDzY6d3`AkwU`@H{D17-CL!KuMoeNojC244C`qkBm zm2%FDwy3Q{OS0ee&A>da+CR}C3jz_@9Oz45K})!J#K}7)cSBGT%EBA5KhI0X48HH3 z^F$B{=}wxUZU+-TDkW>i#+Lb1in(@ufJ}S2-Xi&<;rI&f;#5h-pY!K z1`hW}x2V(}b!nccQU>qwPiZgnSf-SaNpo{@KCrc2N4K6A#JEDcc*%6Q__Ex=wrUN? zS#tjq8C9}ba$kzro%ampA7ohZ^))UYW5104C>wn&qDYGBv)mi-l$yDKn@A$~F$6)Q zF({S0_mr!khuQCpA5l*xtV81~$+=8WFQYR_Mj@*FRrWuvjTy>zq;W?rH{B=1B`!k; z;6F@E3$Ne2IVchcU{M;37SC7;rG1PwHfextCjUZ3QsyT}b4@5z;+{YNjkXM9qk=Oy z*E`{FDpB>DHYmCkpiaC}Bfh9(?}XYF|MBO_VL>dZ-mp__IG zc6R22r~5h`L740IIRyCy>}D(QbVl7I(%Yzv>fXibabHV__2+O3b!=YR4#uAk_atf1 z!HbgcBMT3f(%PCVKzJwTZNqa%VSRn-xJHPb>C&)qd1~>h9G7TY8B3ROAlCY(3m7V`)Cg8F{nAxPk^c7=gLOvdsLnXTQ~$YpXX zzL{FPJ!AQrxnqKX<6lKU1`K*uyLNg*`IOVJ6KjJMD{=_;2QOv!nSk$$6Xd z;#kz-)f{t){MJsk$tB6{TkO^qvHm%F-SUFEnGsy#<~t+As3osV|Jyd$x*gXvnKW)y zwpug)Rpi7NW6?WRx}b>r>m0p&nPf8JT6jF|MqZTgc-$m`oZHO3;Mo!l#>uvCbBCjn zyBo?b5K|OCCiXdtg1p>wk)+tieEd-b*J+#CzvwzL4Ik9lpok3b$_o`BUI-;%tRdOE z*}|Njm(}u7(GEgQe9+yjoE&2Kevw3Egj0i(*x178a?_9e%WV#gV){=Ck{r4!9P#h) z5%}y@-%!3$A)5@oNdbzhClLwq$KR3zk9I3Uf=;EGgZv0&c84d&2l0C_wF6%mn-cl@ zlw`<&IjF@+hx|dU{3 zJ?m|medZd-l+TeQ;dl$#a>d1S*(C6_7$<3G#^s!sj+e=Zjgl-0UV(~Gl2?-}eqiGN EKVH2_NB{r; literal 0 HcmV?d00001 diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css new file mode 100644 index 0000000..311ca23 --- /dev/null +++ b/doc/img/edoxy.css @@ -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 index 0000000000000000000000000000000000000000..79754891f19704929cf6198da9c17f7f12a7601b GIT binary patch literal 7313 zcmX9@2Rv2p|3CM-xZL8}l8lU0X0|Sw*|PWEn~ZEO*_k1_Hjxoh_LiMQi5tS@;${mO zS^x9>{m<)j&Uu~tI?s7N`+45)o1m?we4U($8~}jpsw#@Q;2r(n2`2%seKIzq;0@+0 zuc{9Rk5IUMJorrJtzzN}05|LYJ0X@#>CE7dH~f^0{q(#X{Q_)!9Dsm;0Dc!wH(xs& zZwG!aAE(?M6cYe2Q>ZG+=?CU*TZE)B4}@K|g*YDX96hC6e>X{n{Pa=~W^;q+WrCgZ zAT)}qm%757lk?{r^Q$yAA4>1`YgpgL--Z0X512sqS zMgpDaNju5;ZI|O`PK4KwJVWZ5o1It#&T^#Jt1+1MnSztNAchK4Ch zZ>E}<=?zk65jgwd;7zadYwY&KcJ67qQp1cl0YTZj7uqsrpAI_gnmkyEy!#J2I0^{c z3m+Ut>!inh%}!3PlfF*o#%)yBrGVyMwU)bJH`*>u)LbapVVSyn(g0GP92;0*^wS)> zdiDk{ab;&RJw7xz7=F3+alF8N>Y*t4$3#H)bY~ND5h~}A{yh^-~A+p6455q+T zFu#olQ2CFH zkPI>cJ^mKPuZZWGZ05w6ha&M3CEPsj1%%!Y@2oK8txF?!3V+Ql8x;!8Vt~!*n%r^5 zb|dWHZu=ycq6XAkFLXmz_$)IR(>nTE?;yIBGic+~_;p>%e3ub4RZ@;FWeF?Z>Ydaq@ zQ$#%1Dq(Z~lY`XNJ}B0P=jZ3g58;1rZ!0}{LTOvi2!0s=X58uTJSk9o@cKWwmvt`< zjWDI{P>DUScVirso@?@GuO3j+6P`^3sts#4z`6Anu+U=t$OZ{4~TuXy|S z=4RioR$rlj9rL`1%hMcTCkg=9pFk6cPZk$^@E|HZohm6gnLS^NBYTwY6s9{Sa2s^7 zpr-HH@87?Z9|r7*n40SwlzK2l)wV1r_U`QLT-hbna7D{5D2`id_{vB3EkUWiO5m>@ z9v?I8gBQErC}MD4;w!WprKGF&1;e7B#Z{=4)ne`a+7{dQQ>zAivr+%A@zz#otWZ;4 zAx%tgpQPk8AxJT~XjAInzkh0%rFC_6JW|LQUWC=(h;!z$!_st>mDdK+jX$-Fn!buDXxjGcIHtgpjvD8(i;v}0meSVkrVKa|=hm?Uoo94DX08|-u+ zm^y7w8Cit|5WOhphx=LeY)n;SW8{my{$1?6y{-s<`tVv`Pk%qm&tj-RIs}=ZC=2fe zA9X8fxw*N?IdLo67fxkPxCxQ%o7F~j;T}UNx8|zC*SR^~>-1C^RFiyK+A~Y4XAD^B z*Yw-dAIkh5B~91{(p6yJoEwnP*ghKo?O-x&|3IZoH|81IoZrZq6qk*agz}dkp2h*snmf<^?=AdQ2?}!nd z&0B?&oSyE-o4oQDKnqM&yKf}Ox}u*%{F@|zwqbe7Ov`2k3Nl0?SZL^YDbSS=25Iu> z6B&DX2^jpUQ!|=?Hf^>s?EI|9C(|={kU=XUaQ0l(`28R;gJeRZ{?-iM<&W{k%ySn^ zjHgXODkAL+Fh>l}_b-cvk8{fTS_IIbMgQ_uzUJ`O>ACahbmS4lJK1Mq^&?vm7a>{SVpdw z!*HXyD2wa{O!tVUA~dqYMM!gUYq8PI$oerou^N#?%7NsdaXi*@CS}w`%_aSU^oOX` zA*Ft@QuxNNRA9;#7848CQLBUOu_g_gFo zh+>wa@$*R-4>5bRW$2#)BSVhBZYF_g$5zMce+c^%$xI)Zj_UnP4k-FQoc#x4*cso0 z#6=#!m?oF3Q|QagTCH`6hy8YaLSSu3S{{jsp1|;hQ?1cho0^~ft+ZTjy5pC zVgZ0ZT{_gn+5Bfx{cQt*U8SjURY98TMGuIpsN`+in5h8sC{U4DLeRl|GRv|B$$pFg zc?yC>_M7x5N?GT`P%FpBp3OCiTt?oSBng%PAkLYkDYBRt64)MwxP6h?0FirA`dAT&Fpqk}H>l9dK#vJ<3Dk=%f>FjN7UYbtipOT`=Em9pxpPD}Qbme}w-00xZ3i0Fyn?fyH|bjK`ywFu^jp&vGJIG}kTdZ7G+Iz0K&YV`OL!O6QAs!eXmiI$i$=cZ)m6r3C( zQUK(KN6jTlfRi8F?qX&+a{}b%Q_}*|;oV19KHRe5B;RN&@?^i!?tL4ur7YQc2Mui9 zA(qgDIVvLAqrbiuz5@oBxt{xl4fA4LpG|b1jWfn@Ki7Qo0uwP{mxVj6U*yIH%Dgdm z;8vujl7BonIJg${w*C2wrJ#a`UJD&gkYAith7>{__!vHlgSEcyRm(>~6jprOz`1c5 zR$D{1fTH@x>76JRomYUI#{z4til7S$Yu@HCKAs<1WhBoKR;7%nyY=yfQK z6@6I0M`_hKf~_8AL#cl~=pbN>-_TLNh^DMd-J2ys#jERR*^8brpGDR1R%Pn zsEOl;KJ--2^iL0?mcsK@ICVwo)fK=o0J?T_kvrO)t0~);((K*e2Q6`Y%|!9{EM*Mm z`*w}FLM8d!D1ri|?6&5Fc?;S&1a;8y!s964_RThI<-h6Cpwp_r?pb77U)|B@nOd&= z$y{7q9Co@sXCtb|1pp@eFDQnd%8<$uV#qWae^;t(zJ;tvkDHNA!L76oe3xyrqLI!R z$Do1$!WXqNA^5LfvVep)u199@XZHayi^0cW`!TkvMYUwnRputwTBFtM#te~%r}axq zOJOzqMs!dYC}91qM2RS=zL|G4aU?@@H9S~ntU6@?wO^lPdJYJs@&?LiYECv}WPUFr zrC^qjDTTTqq3Qr&+!6SP06G8B%&FN<(xQ6 zJqXHtaA{Nn_9pY9mk_$VDzAfg@MPijvS&i%p`04X8G-F zjkWUUq?Ao#w%_tuZDM>0tOHqpnF709DNtN}oWc{n^<*@EFJ>3g_v{&cl zzfA>AzIdr3J~9Acy*e4fx?zqgTrfI84@k5-G~V&>Ugoxt{t%8_xrB#b_gWu)7;zWt z-+c(~*)JPRb}gSY@Ie4v$qRm_AO2w+=$m|_-}S@MRdP;FxCoRm{pEHv+0sKQ@US|fWl7Id)wslZR^ zh|BX^Ph?K*y&ZkTfR6fVkn~;S zO?q4!K}#NE2yMyJZG-V7k4JttlmzCpmzFcOGJa4^-wLy7d)@t?d{f$$+ z{nUB9K$;_0+^dO6o7Z2#8ZIaz^2Q=~y{r>FoZ{q*9g4M`xylZOqths>xlO(6EG-xE z1CW(#gcl3l8gK(R59MK6$d#gIUtMsVQ+CQjcl@30{6)VJ1%dtP6 zB=cSwPOtTol1>#8Tm0~j3sYXh867(9KR>YV%4FX1i~nrf;dVvWVKEcwFnj7P?Z)HL z+!HS9ON-loMpu@%I2ZPLF5hmpk@AiHtFd8h2Rd9#rb8?&ER?bDOfp=`Q5YGPqW1QX z2wwUS?1y))O&*0D)8<`}jhz|OA|{xwCc?T?ZvBVT<|!MtW7=5pt_2KNcWWqU)PFvj z5JUisCmP}u5OAEtSD?(V2wX9v)1vVbeJS|Ew%U*;)biUe;(>``I@{H439DIc=%>QJVE8GevOF z7FZim=yhmcc-MKtUqGN^?&%N39;1dUiI44+gCB0t;PB_$MM9zBLju1jcjd(1f*zw#$Z)z{yx zlL}CC24sSpnfv9JG3;0Q-7U47e>xmh^wfs#mRSJ7N<($b_sE)bGufv727kiQ4S0#L zCJ)M-a><_DjEjZ0=KnI;(5zLJ1K|GNaM3nN$=@P%&CM!S=+(4HP2WLB3*+@49OrmZ zX@SExgrFN(fBY+lF;Pul{;OZ^t;dzzVQR=C({VHZWcW8H>m>j6wuLN)v|<-i!^wvC zgdmF)Jgp4W0`Ue@08R5{zGG`*_=G=ubIIz)amb)+-hkeBGX0?Ldq3on3*l*Fj=hYV z@EG}9ATCc5(!=_LGVeeC{=`8$YnFi_za-NUl2g0+%=i`E=&FxU*G}Q0@HB@exAe-( zY_H7cKMlEyFdZp)w%oDXxnuH^4QaKT#i$!w+B_>D^RO0FFc@--8mEczguJ)FPPxzR zd~y7kUouf$IUuY`5JmrH`@<@I*JuA;mO`U5f=1gdydWDPnK2?eDZ(MpfRt~Lq+4X3o*9QG0hk`m>+lxk9)3WyR z4mWoXV<|`q{NC7r0&jHhz8Z71!IbZZ|J6EM9dSd$0rBo2nUK@G>^ll$m|{Ln*_zYU zjwTO|e63Qjcz`qw?$I@`h7H0nO%cuICwg(^r(Xv$TPxJ=H++E&4>g(_jdz4&MRcdm z$_`)?>{Fil+>spa=gmV7lxW|&n^gFIK6sMcF!zuTAnz%JI7 zI$m)P&fYa!RK`^FYSHl}R-l{r#If=pIbY;Hl*AT;$XgqySsqv}nC@%@Eh_`JJA zSHI{AtFlv}ov6uhsxILgWxjbZSOzB$s)9780Yp;SsmIt4A62>R%qPVcPBXiQcU54*Qo=`<^lTH;<_O{~}m!eXH*@d;BfA#8pG zU-%u6a9w799Z4~*F-5Z;c-r37gY9u&Ic{{DEfa~9M!uasuW7mhPI#Pxw4EDG(bdoR z0}&Zfgb)Vw{VT#<52!tBk-?wt^nv%qsat#akK)8r_rV z$YsfJ%N+rnRsnI3V*P9Ydu14vhtR#2^dL7bS<#?!^~4ABy=YU!uvj5tAu4q&n`-!L zk)tcjz<8GYOh8(h&s5fZGkb_gpEsvGTs$rF)bd4@m|;eBzo_kmr0A1sTWxX1{rJ?(CQE_etO$TK2 z@L}@M3qHkc zT#}G?)3)ANf;u5Hbg;}+BaST`rakW^#fePUdMotc!7>+hf|bWY$7$iw){HPkMDOUw zD1G^Cvw!x*3_ChIGnh8r3R&pRdp}6LMaXuex>xJ!tLq4Q-WC*7GPR7$N9K)UDv;U( z+v}f&kliVzscLHzdZS~~fSq5bJ*nY`rC1%ypC2X$PAuQ8`?wXpJL+^Ts9#qfSW{)A z(7$H$68@(yboKuIy4E$!^^1!O*5m7{KA_&~h$JOr~RK?;T;YsN7G{|fU z^$EeWi1N+%TGR^d1Ox1 zlJnTZsCczH2BB!3!zoXSRsn-F-{3OIkj-cIOdZ9toAN(RrT?cX8Km6Ti(;;+H6!5g zlu&q;J;V~SrF8Ppx8o?WYF^*H#3MkPwD^UyBt!ysg?^Zr50s3);=9=aqNFQN5VK*G zOTT$@QdhQoVb<;>%gM>%VVAAhLs5c6F=%;3YsA&%+nx5^t~nE|2D~I;D=Q)$t*xg-CpsNUS&W>hxbVFtTVY z?(U8V5@AwOR#rAR*6(xz>1>b*6-1%T4}|w~WL|5ebnSgYJPQ3?9Cyi3wvi8Z4e>kf zBx-K$?sHD>mhZEt!Ek#|Y1`8RXpP<(Kg}&HH69E3dw9r}uZ15@=Ma@Px|b#Y;I$tJ zO82UF!*)YbSs#U?h^{dF!3}Lst}x{Z|J6%UQpZI<%@g;9db=U^%xS-@iR-iv{WbOeWKGb+aM}`y z9ZFAeM{{1?9!sBMutWGi-XctVPiYNyXXfXV6A}^~4-w@S zx~=>s@PVgx+k8yC|3%?lkfld|*Wp#XhP4Qof0^sqw(dqmL{ykOgr_s3ZEtS}i|pyv zPoYKBYYmdp($WPmhG%oE=QvU`5KT*@*oJ(K;V19PQ^5Lw+3^tSt)e&~NGGJ|)xOtZ`F^nnSx>PyErP0VF!?6d-0z!`)%NpYrmI@|4zXm`Pw50^}wN?Oq^QaH>Vfl+fa1rvQfSIpzzG6?y*e$CI%)1(d|Qc5&{ zK0$EzAcR77oGrz%E}VmCmBLOJ7fRz6Vg`mQNA!PgwgJ)+0v+B9vDa^Q1y7qe)quqP zk}DwpruOj7}S{3p^r=85p>QL70(Y)*K0-AbW|YuPgga7CvEi%SZD}LFVdux;TbNTu#2R zIsJTn+kYTPulo1Ll3AD;2!xfDmD#wLvj}>v&@k-CVP=T_%(cphxuXQAk-^i|&t;uc GLK6Ub>Mc;VkfoEM{Qf z76xHPhFNnYfP(BLp1!W^H+WcuRXD>A=l%i;Wq7(chG?8W+i%Esz<`6f_y7NWHH!5o z63R1{^0cb0vMSkFaE_%x<+7O{*?Xs&Ff%xKT5jO&GtAqcqoa~}b>qg&H07ky z617wnX2HUfTT*8{kPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ8 z6%`IG`XD&~00I3;L_t(o!^Kz8j>8}fODg_+AF{uksuh}hxC0rJP`W$mkkHl^jB%XM z>f`Y+`Dtd>`gxwMmr`2KIk$cshdiH8N#}XW6$o}5WA?p%5)sKc%eHO9fR!#HlFUqU z&XQ6Z1~3DUmCHm#rjx?$lu|lm24QA+Eh4g2CJ}X<;QbGo;J_$CohD|s1Tu}z3KIrH zRtpQ8-Z|UyQP4caCB~&Z3QG0mMzcQLYIcQ!(sFW-xf9knF@|(?iY~XAOhHzd%#8OD2m>x}XSSsVf@;^obfpX48<@ZgFF$M4@xtjbM#B=Ojp!9yfFNKXj22K7STvD?00000NkvXXu0mjfB76)l literal 0 HcmV?d00001 diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png new file mode 100644 index 0000000000000000000000000000000000000000..de97c9268e4ac68310c8b92d6ab6bd8a245611da GIT binary patch literal 1200 zcmV;h1W)^kP)002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Fc5TrKj#zpOzs?z2=A0p@aw&u*pMn|G)ug+?Vh;0+zHe5dVLoF=!DBW&zJ?E zp99|S_j0@4%Io#|xG+sqdB5NP{rn5Cj%O+78UIn|DpKcsK9>`B2V6JsOB3oD&r;4a z{-e%Sw9ela{A&{jdu5*U-Tgr1~ zQc-ZvZCmQQrCnTG+COg8zWQ3Lv1sjNIKQPlR|Xsq_}(oT0MbDS91lPg3>xeBFKokrh3I+f~!N36>5GNtP zFb=56FWNP#oK=?bNEQ~!rtXW9X1GX=k~FL`OjOeF$R)LGB-wAZi(5xddgID^{pUl5 z$!2zVWE!iC5c%CAFL=jfl{TW1M$7Wjcr9z}SyPKmlC20r0B}G6Q80PClsJ^eQ9Rdb zuHflIJ5saoBdvW)J5o7`LrQ$sb0li*FS@pt^@$vLe#kJ^<1ntHwKLacEE8!V_VYY{ z^jk0Fa-9o0ILfhhgnDcg*`~%yk#UNgFLkMLQ1xp&>oHLMt>=krgKLZ9aoj&)eVyWk z+VI9yb#%knV zBgOT1iW^1q->g9a$6utrxv^4Ql-s5#yS%xS5>LwpJyaYZ1w-06F426k%%gi2p;YTL zn*Zi$*TU&q<}Gq{z5F%GPa}Dt9$}k233)sorIb>h&nNZ+VE-)`LNtIN1b_p=0f8Pk zSwvore6GJZg3A%uh&UU`%8A$z3ApNcvGym`^9BW5y;mkO7OVYaI#wj=im2;bzSt*w z8j*3rXhhk-tiA%ik?Y6P7yM_$}>d^Cl%aa8a!%A!J=gv)gqCjA%RAmjShY zk&jin$jBj)wrhPzE#o_v^@kLW;DnK~k;Uxogc+{8mlL+=3tKP%4hR4$2Lynj z95C}RO)LJ$<@I?2i7h|tH#%lcU&}tk-(ol0<1_foFDdWsgqjV%=7cRA;M<%KLNw4f z2!R6vT{&RuTk7799C>JZ4;!>{ThW;;ZOYD_SA%VO2ZR&C3B68;Eg1NXEf@e0gaF^` zfS#=57JO;X{zkCF($|*uL^8|wn48N;fkQ7R9I3CpA0+QRH%LYRy5b)R!`g7p731Il O0000002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ6 z5FZU~yaYY~00q2BL_t(|+U;H2a;q>5blUuRzqvD+7VvpFWE>%_)?7k5*?npguqAmd z8(5Uf*Vk7qf^ZV9(=;gx!g&NNrIcY9%E!ltq9Ht=fVI{#3`4nIuZo7C3@E%I0mpGH z+6xLIpzyv+um~ueb`dgXz*=j$TrP@=0TUO+Zl@)sQ3vT-lF8GjhNS)Y)Np5NBKI{~L@T3m#*2iTKp zt@p;JX@cbN4E2Ix|BjCFg536j+O}xz_u6Q`^V-S$v$poy&cxQ*Y0r;rMq}sMi^c@` z(Y9kbHGfVm!D!}MMH6RQOQ=PVd8HOe5K@dz0av&_)W-mG0@FVnX-$jszG6Cpd6iG4)S zD4R33W^wegr6p&!^ui1{3`424F0w(E#-nu32HZMgjcogm$jB1kn}usg#Vp4?lQGIP zmJDq6inbT557~swV%+wP_%pYAzYQ~vV>tL(hik9?P_~PVkL=oF50e?tN^s;oR77r% zlT|&VC}Ga0&tEJ%k7- zoJv4FMiNe2g8%YGh@d4{5VmDN2~q_u!NU6zP)o2N0s>_EwNi4;;4^G#zyC`L>8-YI zIsZ<;Sq-zMv%STs5t%X@*w0xZXGHX=S58L)URT4u^Pb?4-gC!@j zGZO+Nz0VPNkPS1cMpr9pK zPzLm{wVGyxy%obpDUi2TLEY1CBu?G4a_w4M*7W_50a2rjQkgL}dUVxOnilo5_XJ|? z^0b6KgUQ;2DyO!8Gi7vpi4|3GMVi2@-Nh0d2`yX4qE34Ty0;9h7ucR!#o2^lg6|D> zq>N@KDl1M!v148j=!p*!BwK!Xg({IeZ9%}cIAvzMSJ)Ae5UHkn2oMDWN!z_bn~X9f z@-5QES=A0wM|(C$1t(DkMz$~$G8#J+SMOZ5Dyv8A`w~27zqUXna*hph7O3bmD~Gp^ z*;fa=*%<}bla(WZrnkg+@^mC+kFs@kF8aj)Hk+cY4=Q!sYBVE3usz00Cd{g}$bgX+ zEs`2}PM|AlPwbhc>#U3~dKV?KArhvt%U4th9!;L?oeXA`K|g&EO%g=b=rg7ws`Z0W zfG^}&b8$*k*B4={a+xJocKjaIK(oCqTOT@;wzHCX)@Jr%Fnd8LdMj})ftln4_kht_ z?hOuGQ#w0_X^UxNi{yO`dG|z5aq*tmGIh6m-ucZ4$E=q33^;eTcR-I+1i!M{_!a$H z+wPGv{WJp#!l6$>RG?fqm4Ls$zapS;ZU)p6ES#PJ^<&F|2q=hvg78!V{`~xifWmnM uoCT@+p&H=~TxzX#9LMtc`Kf3KPscx4r4cOw-wj9r0000c73e^-^QHU$G0h_3|cuDljd5QbT#Je?6pNPP^G($^aTorE>q=yral%n2Rktlk|u< zB6SbBG`&ZF=tG%tj9|RLw-;=+A0K(VYgY{_m@_Mu;#9$;A9&jo($nUG3m{pPG9sKJ z)-SrEJ!oZpgRkTbv#N2w?Avv1g`*hj3@X!Cn+Jh2Ml;^V7@mz6b|Fo-YFT&Oc=qw1 z@}>V_jJMQ>kyo}tc5CX?e65}5iLW`a*?=JPI$Jx)*JdpOpdFk$7LNZlSowU@cr#Mjx)>#Vh2qRYMG@4%U~V=*(;bxq6%o;REM)$>G`C7nd~m&p*#P>~ zXHur`Yquq~Y&12(1U{S4izUj!VqeX6#jVc9i4wfL*s)~-o}QjXMEK_BCOa2bR1e|w zfOiwc9TpT4;xRu`3f2tu^&xUXTv-ZkyvdBZz~6YF9A*}l+0tzM1w6ihdTKaGCcM-b zM}+kR##h<)t_vDPGSvAu;zhryW3SGaF8dM)M|gO64tMi+Iy@ydmbFeUae-c2{QNoG z(9m#bJ|Lb-MPIsvICAtT6Qr%J&FlJgLwoz<%m(`4rx$N)fyA(+zm0CXPABZ`Y;G;L z{_bdyy$#F#KH(XXsO3Jb1Q#zc1fq{*U zjYV~JP>U?NSCL2Ad=K{iTFJ6FGWAV|A0&YtJIM(N3JQvei!+~p$aC|>Dl6&yL|#Xg zIX+2Weg&eas2K77JvQjh9i*O~D5!_YojcEE+(AXktE#$w{w%LP_%H5M=b04kBWh}D zxc2O9VLyNW)gECtF*P+|5T~J=o2apg$$#_(d-_h^TCnHtq71c!2zRWxWDpjn!_UuO zcWv<0kxLtcNl8iN)zxTQTLC2}o9m(byTL;$JWs}{A3oS^ZEvS;Z{E>Cp-_rSN|AlCExY6x%V{lP3aGQ&Z}<7hzfQ zF07zj10`OsC@iK}tTCCaB&2|+E-(9l0(Hy>@X!C-*+HtR-ujI2c$AdYyXh^~)F4Il zzzMlLC8a)YPnWbhjIFPa%gD$GmE?PCduwZ^?eCPKudkxBi;LOH8N8LwW`;LSS$4%) zx?ENsdRA0Kgd_bexl4mJQOGB;;>g}!^1**?gy$7$wPR|Ei zVs8!%jpMNr88)kWN^?ogde$9cWo2b)X&FJ2;y!k)F9OgLp&JTI(cO{q^YfcwF#H{j z%mHD&8k`>k(lj9Q-C;Og+VS&=mg%exwn**okO~FI#6R7i^cR~amJZy`{L_nl_Uzd# zP+riFoNM<}Q<iF240XUkipnh)?rRKXHCsH%<~~eP9Nw zkqau%sz*Z!{@*$FcNP?o@?cZr%EaUjMedC|I-tV!fV+9RVQ_4jZKfCbIfH;Kg45E_jJnnwJDq^pApCdwVgPKmHB z!=6@FPNzCr)C6drgvA1wG8MJ9x;!~AS&DhwVSc;3B#qv%<6L7Hx)0{h+mg+0 z0jqK$SZNPm{q3QtspPPKfBq{eiS~+YJS!pb6?`OSoRqamr_%>N_q^qN00y+O`IQf2 z+ONq@jb3~&ch@XXS3^S)t+$ts^fgp^l*D2hS>*bVDk_42(C2Bz#jeZyq=~0Iw_8tY z=KJ_03RcSYhZI2ZA^5$2n^Z zhKHkI8AsB4C}Cb-U2XZaezlWJK@9Yhu?X!asz+tBKS$Zr%IdX3`!1>nqM47)$jG={ z6Hw*j?B(e@8paOM)YQD_>MGBrf)C%jMf%)G{A_Ab!GaWc-rAa)nHj@)ozmsgEFfWL zXIE5Pd(7NL^`S8bMGS3ZguyK+PiESq78xme#+H`U#qGE0lGfJNvkkwHO>4CJD>xwo z1A{jM11ylm>2^1Vo*e(Pl1LDQ5Ws)HygDLK6i)xZ|&>dfsOPKeXm+M(}+hAe4X z6^(1_>#6teN95%pc2{4Es^8g=`ug?jBeWA}$-@!V(E(v)V{=!8L18fV@bGXsTtjrf znx^KxYlUG#U=E@&U;>bLx5xnj0W$+?(|PNsIb8382bo;|XlLL`xUQxqTtr0V=kjuF zbF&(t;zeg?&f;NqvRMLSa&mHZZZ58_PO-bU7l}ggM@B{}!jl?)gFFKHeR&Zq0D+2% zretIY!nj${CML!8^?U#T%DQSrV~56cXy{^gjJZ5-NJt2yBl4*FtzUx9&dx=n^A{Z* z<3>hoGP1Hd>2zVBB+57`HanY674K}2^S*xF8jnx@@#E^^RNIN1oSaWB#cMgJ*Otw*rB&I6XkW|M$G6uvyt`6=4Q|K`kZ_71o=n5$YD92 zJ{1C@Q+zl8Tt!rSyB;@d6scf;|L*S2Lai5x)ZLRPtfZ|?1=~Oy8x#I6Pp+)3br$G^ z42_NbX`h$s5(7DsmzRH{J7@@G0_>a>lRU=kBQ^b#^fF9~Kp@mz9e@J|CF~Z; z=i}oO1g5^dRdnUai@D1~BN_7E-_c)hH&#LIcW)}f^hZ^u!v4CB{}Fsm_VV)Tm@5qD zjdcf6#)5f&1{ecDqyO64P9`KI#K*@&x)g(!n&@@JQ3+sRI=q{XKyeVzcDKRmK@VQGJz^%tG zO*DH_jWQ#&1@Sat zu45x^o;XwQrjLI%y5Cr6|6eo|$`MN}mI6S}%?;gTi+K0Wd__BDY6`#c=MU}03j`ox z^qWHiar!iqj*br68Cc1Nu2gRuM_H0oc5HR5WMzw#YBJ+Wsm%9p=9#t=@;89dymqau zKP+D>F!{yAmoIV_{<5;N^>;SCQP(Ui607kFI%@i(8yU7p?}*InZkocy4qt5dWs-8? zfgi_Qz*j9%K=LhN|IXK+Sz20ZXd>1-)p-pgacyi`sG&G!rFa+BE3cgJwAxW_)7Rv@x}L8Hi5g8)m^f)$`%Zo^$Fe$C*4#&IcyP zTuCUCJ99B!kPSqxM+PGiaTf6Vfk&+*$E$$jRxR%aUrp%tC zc`ciKp-7nQ+FnXz^ui&W%jsgoL%~BqMElvpiFVTBTSeiLh06FIG?@7+#%|^O zb)=2*Cuaq!YddE*;Te@rAR8FHo4&XxgK+mYj!@;?q1{7pJEw?3k79sznw4JriV)pqR0^pWb;Ds z#P!76d?g4B?@=Z3`_+tq&hvgJ@sMd6RJYGU9~>%UCKcExjQzEUj&7;sc$p zwTBxM-Q3^nX199Zmbr-mZS~XE-K$@#mBM>r%{Hq!Le7hF`Jo15h8xH)pnkQAQN)@s^kA z4XRNt^0Bnl?C(nS-fbt?vM;oe z4B$3U8zL6uVGa8oR~Va}Jrkg?TJewb2;N5laK7w4HP!@#Nw`0q)-I%Y;a3J?Z+ujA z2OcoDuVmReFt}>Zuz&aa_K*@EW)t-!M@5xuXtW|8-d)K#Qw@6S-El>-S%Y-;3eKJ> zR-`Jct4Sx0ma1harsM-KInniE9gP)Dl1}@^MxRCtpDw3A@6UA;9mXCOR!14P$SY9q zov90kH?_B?cXf%LP-Bn@1R4{OiTVmed|n|^Tdaj26STDX5Hm&97mZ37y0-kL;|`YVW)SD=|9EA-aye7{Wr0~u7i)c( zw8v(_aox_dlyDaYt-6Ho6_(0Lt+y&GFE7^-qx{bD%4_wMM#i8M$brxE-B5U%mO?yZ z=HnmApeP%Vvml`%r!0lO!4RC_^_z^yYc87rtd^BsXA|BYLf$CZ+mv@AS%s9ata8Y* zS9*(=4ftzWFN@Uvf-$<_O6Pl`D8VyUa;2Yh^7q_*Fx4?Q_CGlhMmrrP^4!wbH`C2_ zD;iK`rze(9SEikv9siCSS^^~6F7z+_M@KWoUCc&R2A$R{uYxZ7(Uos<<*pR_Vtw^B z)ULeb<)bdPJZ}zvL!(Ne#s8A~(mnS`Xoc1a9v{67krh(qJ=)|T&bIHPmK?@;GVayh zsj>@ILEUFdeTDz1k_3F=So>b?Y99?535|+6Lwpiam^`9Ty_qSb z3onn3RAy^Jo@54;S6HvS93nCXam74uAoMj36`|A-Otem)3 z2F(6^VnuqGc;iLSQ`l6XR&FpmHl{G_2pgahGzSl|5dU>ZYE&U>0m%H_45;P9NTrPSiSLoez;UJ_Phq`C0c%jFpWhJsdZ`!l&kOM z_08smxAbJvYS~^8(`qb>W2vXZ?UX+FiFL0S&$Kc8cA5M6rBkwSOKUH~+gwrVcS<7j z!R$AwF7a;z>Rv~CNp`_#zZCk_3`j;LKF+PKt-Zi{2ytw8WNCU?k`3vx2iupT$Si(% zdw_(YxK^9R57miWlB#?5&>#~$uE1^%_)$F_e|1x0boJ$lGz2AtpAu@;5Uug1pKabp z#u|bWo=5p9p?566c>{%TZ*pL_FaUqwzvNi3!QTT%QtNS1K|f`1AR zo1R1T2)Zj#>(5JY1wto9B7!tT$~x%W^}k+)66M+SHFctJt9&q-PVZpLLASzqXOG}= za1c znf>e6uR~3A5}jDQYZ;Em+UM7PYI9w7|CQ}Bt+Vaff|Zc1Zy0;wTuYxQ1{{qAx8&Gp zjy*@&u}Z3ayuE>)@J*9^@1&9Wk%+gV>EzUd#j~kVO1qJf>f++kbj;<(otl-^WL1KM zieLxK9hflpAHBITx)i9mztx>ph}Usg_^UtcEXJ=zfJHrN1Cz6GJr3PK&A+fb-0AkC zbdnuMTKhG{(eiKFb^fRfT)e|rFr8nt&yALGTFni>P@qr!bxgQ}-`yZgSWUC!D^+IvvpbBtBDLNfurYYc@M_TNTxhnEeGOl}X?%)v z^ua^XYp&44&8_usz(jbOd^NO~{pS;e*{;FW`;eJ#WNa+jvNedbQ@JnAJEB#1QZC&~ z6%9rcMnXbTCc9-Qb%dYLU*6N|3b9$J(!bvIEv?%{Ofo2AI;u-4Yq%`%ERR;Ga#)=^K_$kw3g;rWEz;9@lWKl>3h|l!AkL|M?s~fBTU~ zOl0q-Xx~Tty{13=;aDRljoA?b{lHIpG>O#BrHE2yc#3q^ z{fvt99!bT5ZeXyWL3;b7EnZYA6r!QNM^{p#Aom%VC{`(`Ef-mYQ(awMTL$l6US7~J zFzP%m)}iKpw~eeMiL)-axVQ>RO3tT?wa^S*7%Ixl(JdPrTPyX5%`)>nW3onhzYv+` z`e#=kFVHjZKEZmV$QJjWLVsaJ4vK>5AR7-Kb4lK;i!qT&0~DT_xuh;QZw!;6LL)I; zy*8v>2Ra-rNhif?G7o?Ls{#q8%dq`J+<7~|4kyfymkNPnR4_}KmTV$%+F8`z1Y!8i z_X)Q6w~~XKkl^){`uQSuJP7)SQN&UQ?8#~qcP-C&x`oyvr$oYXze=21E?VF0`LDhyVQ}!YL{$ z`gp$`9w&9Wx3lC%pC#%?!fb~}d#%hwMQRDllpXQc61>^z5#|Ipg8UI5++~bx3n)}3 z$kqJswt>2pq>r-H?!oc-^XDX-S-Kx`Gl#XNzcTnm$8P^I{vq$-kK)`U46Va}7YlAZ zDI-ictH-VPKNnNprLii*hZn(aY-u@+WaJN_Yuv@Qv?{I}yA&L=ldkUnq(9Kby79@0 zw*@RfQKusqu6_7qwHff%KPsgx30HnZ!=;tRVmJy<6{|?*C_;9iQ<1XbGvgrvJ$NEA zujTlciakn{uC@V+g0_SQY+D+M_sbGB-rPGq?3sNQ2^?u86?GR)P0es3L0oF_bYjfm z9q9vDbO`p0M^)6Xx)!nVlsADZl13s@@j6`7Hz_PTX14e=`I$zxq2jLrJoIms#fd|~ zbY{t1_YC6+dPw@_Y->o*w0{urng{lOK5yvtT&pyfmu)0?6nOk2aY1->iS)^je)G?R zckLXBi`O2}-o$;(k3!nmYA7q9`O`FtBL&Ylim{!V>R=L)Jz@m8eSj z?Tn47)NfC2PZlZjl9=Em5~)T6v2Fe{TDpt&2)CUR8Mzs@`l&Hqt{w$lw`tYEn_SK@1YL6brlZkP0MH6q<(lyXvTuAmi|hQ&i1TC!Ya z7!ez7QjEvEM!O@c9f}g-*22-W)|1Tz(Z;SG*9)1CRiu~OV>vQwTTEh-3z^wrDX(`vHN}fE zGNXyYccb*8KK`9Alf^{KVdj;q$ZQ8FrzDYkwUG*Xi+lw;Ch1uMt^qq-!7d1Y_3T1Z zx*RDYaEQb6^CpA)yE|1zyu*u&Vr53Hbc8CyZhN~%m7@?qLEEm_t1;rGq@*yasFG6_ z(?S^Vu8M{vcVPn4e{esM09T6fMB-Owv|`$nP-w*8g`UapNA|@JY+o)*(*IwP5J&dZc;ZGU zBTissxY&mj<)W=A(D32JGhkm(a(8w+#0<|7l{9qNTozD*MDTRzh}$SK?#P-E5G*?qZITlf8Bb zT)bUg(F_K=!#l*G@x^ZTAK>7h_>trbrq?EZbGHznzPTL$-UFT7$u+CE@r2w_s!SuePtOi&*GNfekLeBpFMlYQ*=MICkh;5@7oWCyf=*yq1(K&epB=MgT|bhJ0SwostcDMVr;zw{b~8q{DsTRlX4y*yVm~9eTgy0NR+aQ z9L5>fWo*2{qlWt266@bqnrh%QCE?FdZ6P~0orbT!^Q5AZhA6TO#ua@!XzMYpR$lS= zXsDn~Sz!a>R;&1iRWDE(uKliJ|NDu|hKj^yI3=($$CAI1Xe(8ug2nGUe2Cb6qXSo(Glo zirVDlZhaJ3N`p}in9S9!P|!#Xt&lm_9+91Ys+S^(Cu^vtma^H?K~y6(6e5l$ViB+h zcCL4nztX`{&!3gNRA2@8xXR$QwY6LC&eRI@`!eJWBs5d^>(igKr?L`VZy&^@l-W+2 z5>zL+2VSb&atl7vsUmlbrRAl4WdDku@XIpB#3iO6 z(N&caatF^!TTsxUJf+4x?^(ARlbjxyz_|QCz4-;U5YBa9DXNI2=p4pqrU>4P*iPt3 z5%cI+r@_0%Nm!zFai;;7np@3iMs!~ct~SuGY=5wBe2`I%EBzg-=;%Lb*}uWh`S?J= zbTJNl)SG?H79936Ba1EoXIm> zzA6Q#k_zavdTkhR&lKA3p0-p6`xQ$(v-@Zw*pX_0_n5UhBWZ)6fNYrB^A+LdhBum9 zw?ce$?S*u;JIi@L{K;h?@%HgKy12LxO^G7pST=}_jpY#(B);d3HJYyAjl&)!G{mof zQ2;eU1K-Bdk|E4^YHiJqcLF*>L`K$NFiKBnkK&RD6S2R5`11DeL4LR`mDHB@|9>Ca#|Ke(vc(ZXvl{{cYA7NWs z>$B(Q_A9kPL2$t2=Ld6+`SBx((bC$Qc|x1!ZAK5RxdWcsnuWspg`Ek?Gm!=Et|3A7 zbx(LA5lgZht(PFy1nKhH+Bnd`9-f^wmXyF*SXvU3kkr}!4nlZKL_x8?+54^ORaiu1 zd~uNo1hgdomexkJZazp9M9mNQEz#mFU_Sp)K21}$hVaX@ zFBc393Lu2mp@nGn=8^hVxERbMo30fUm9W^Z6s2l!6vJP*o~Io`g*w$KEl95NZ+%a=5I(C&)p(Zpkcz^5%nG{6f7_h>(cxJ6{?rS&o;Y^{ALJ%wH zK!6mb4eB2RlNt_F9PbW#i^!8m;gLqFQc)|CoNr%8oSb z;)wnDhEUp=iJ-KCS4x{h^3y7EhoJyLt!GfxjQ*D|lYH?zf8iC5j}(zxGu|VumrW}w z=Itvfg|gtKJ}(4q5MC~>;4utDK)~CmhQ@cO-ZWd!^Phvh3LY>N7HHz7OAz2Z_#g3B zMV)wtJKp**IiKQht3q`wd{y2Afam)%vA=Ed{-D_A8YQt<(t?@~BJPn~rQC+xOCs$^ zX-VykkU6+ZE`TYmumu>Wn015paV4N+zATV;pIo-PI;rXi0^TYp+ji?mT)!`k4U51$ zxG(W7k>Ns>YGVHF_Zj}RJ8dtVJsa;u+s{G$w5E1Kvjv(abW+x5`$l3bDP%Me*T@@Tp=dE{`gyl+gC0 z9&d<_bze<$ZflFsLDC6)kL17Va9RX>Ud~7?|57Q7WqXVJ&3feMn8g}mMr$95br2)> zZBPxoCve_zWs~MCq}=v@rBP2bO}={R)XQl%)?a{k7aETcrR}A z;20v)(onMn|o==&ugpd0d*J$>O~qdR+RYYPYQ$B!Q- zL`X8R6phvwK#yySqE_4<{l$-a=q3809o(-7HSlHW7 zs6NDy@&m>l;0M8GJ^u?-j*hI*er^Iy29Rd;_lLxcKLE*MhJaJwUj_0hCDI-rsklxl zMr(*7VPTfD(2u@EG-W0J$i%rg3kHbh5Plf6a_QcKiFYMSgUT+eO6N{mIuEowycj^N6P;9#{Ux~Q?Uib zhdtM}-Qb~UQhZoQQAU;9m|4y&8gQT8Q0YUU3{c=>Av`)358gf35n2YMQwpbzN`&b6^x7?0Jr+_m0+ZxaFj-|NpDyB)_Sd}%vV=I!_m4bW){}UD@=Sk?GV*m zl)G$EzmbVd;ib-%Ridfs>Fw|A44CED&vWIP`jas+F&!0c(NnP z$C0$FNLVn<<9zj~H018iT}VjiBfcOfr?Q52I0kv0q8q8Qcy%b-vZPaKi7n@ecm8`Z ze_Q>@dLzDnlETI^~5$tn9$Xe3s#KqzVKMqi)eMy@O6?w`qxC=i5tx1+8a##Ed? zLbb)%!DP^#hjs>J_f=gV@rf@gx4Wv8bE6g2lr%NboF+H$Fqhnl`t!>RXn{L5x0E=kqo7CreyL11BLecTO?wU|&D{%uY8io%-2fUoZc8UTB>GOBew`JOwqFLL$FZwI|Hs}-0 zB8YbyH>{dV!^Hf{i4>vEB%7kQp9MRmJck0`Pf9FqQs$W+gOto7`z*{J1!yU zz|41OPK5Y4vNlJ&cf-4NCkEbZ?+!BQQ}=dqMm-#5wC^s4j_^Wm@_W!F1=)VPNcp~| zOK6wlk)p|1JLqurmN6BJm{UCXpm?w29f~hf@a{+5?D!F$zAde036B<-(lAYh^M|W% z*W$6b93tH|7~y-%{hm<%FH;S46$|fe8@Do%RYZ%WmZyCk#ENI2>$qAr$H%4M$2bsQ z)r!u{&+nIUE>##1$O6#8g0%+6F!G%D+s34PX?ke~Q+Brt964(oIWKyO zYUmIuQr9wMxbzZFz24cQ#3{yHoAl3=wb|-olBS7IsNOD1%Z~K`h)xcqdh- zt=xuWypIw)*+|ne)S~!PA91vD;*1l%q;$+r_z~S6$e0qWnaSdTl<_3S^swpCL~A8Bqu|S%x*c5hNKsa z6Y(Ku_0xBsW)4{r{_}Cit7cR{eLsX;A94(4m zHZ`5qkIirzRS$EhX2xtml8#ql7_^L24U8c%7 zG@TG%!Fan;KyR?2HBpDJCH-JwEy|=2T4&^hFfr-(JFgdykrA_wj-Po5+GIo`sbjsp zj~J7$PEiA-fM0rmjN%W_2SieyoSYyS+1vjBx()mFj-!>}($0?@hFxUsh% zI0WMj{jE4Chb>O_{uR4SO^lDX{?icKZ1H{MPUbMYv&#jdau)w$X6V>td96>TTh?q6 zQ&kGnQ1m(3pE_7`gY^By1|SPj0|8Cut;1jy4~k;Nt|4NBdsO0=Iw&dyNa=Fz@LUK8uhw7mrMP16pE>@7_z=z`^=|FZz+X7HeZ z({oJPScG?l26f;g!GQhxJtz3>xsir=2c@)$1sj)cQO>6;)FJ`6L`m-aX)ZPrh1?!I zT5|(C8;Bihk<>RP&XnK}M96gnu*8$(H*v0aO7dShVe&CDin4Fu)Ohtjbssc*{my1_ zbpkK#bYEtb`5~@B9bW-VPg@38B=D(7O5ViYKo9wQjgcI@0I@t@L7hW5Qi6UO5P$Lk zK-o#(=@)?bQME;6VPURQ{r74-=9cP>g`CxK71x28_DW@L1YLzY0c@E`PGKl%%0~od zT(6|NX;$S^j1mLOd88baB1mpFg9Lv$N=w5mk%DtzrLpP*2MVIdpltvv>8Uxgot3l(SJlBh|P zKvURo`kyrB+oG5yZgH!2k)t~+i#)ub;fn)jCSrB_?qB8cV^2W|ecN4l1P{CeI!zKi zuL)r%cP>iuF};aAD#i)Y+#HC2ZQ=fuxSYs+IyJuNH?%PqYawX>jGz zs_b)V>!U6U72+v~Hz|eG8d)Le4azcjAaf3nB#z@Pyx|?S(dpUMI3yulGSf;{!F@@N zsE~{ga3PUo^0*%9{9(HCIfLDlECfnir<7*%v7Ae7N}SBi!-iLHu%$9HDTXRYmJu~H z`1TKVINFu+TYZ4XxorakTj2ldC{|IC$JYNkccZhjv%>1?Nq1W#qrl$YUg&G1!-gop zDO{jFL&YXJ(WGT$h)GH7GvB{|Z)sxEch_24%0%jsg~xzw9<$4WS6;}bnYP-&d9F+s zl~0kKo$b*m!AwKHpxYhtLQz_XUh<$FK~Ch3QKx^+ zoC{g=fmBA{x9R%`Hf@6Ljrr1&jQ%2DdKLwaPX)^Nj9;VD9$W()9{?SE4EjAcH_+*G z4>U1AdjUFMZ8df4YH>T!_-?~5An?`i70AT#8Q}EV-O&RP-eN5J+Xzno1Dt*kAcWth z6uhV^WsBNH!Jb=Om8vd7I$|=W&Mbq(@aBJkmbs3Q%-o(y@m5^zaR`q2LvEeV1?;ix zcPut{dNiY6@6~!Rw>v*CO&MJw7cuTK!78Fr3WPn*7uN$$=GlO}u`!;QjLgj4odCeg z0G}k#_2sYIiicsRHw<7X7YMkOC`+B7#zcJ6{$94$)+4-1W${DeY|Yi({j3Z+_!_e8 z+f`96984O6<%QDdKP07;9{&Y=AI_%gt(W(`s75f1SlaUwvj8XPDrh8wQ1N&~yl)tx zp;ss8bVu;gZip=8<#;o+RxrG6|0O#=iiC#OAjjYHjOU5c9U9H4L*mu!cYH>M@7#R^ zdg*(g=^a(HIx#`r(o9S8Yk@4kQq?5$r$PDzxYTB${CVt59~maR3Z0&T>%x1`-{c6Y?winzZ*}!EiLUZr>&!7KgQ2E~Q-;FH zrd-4Ypi(4N^upE9$1B?Q@2(PIT{ygDH?0aK|22UHn+%rMa@+pb(CY6Ls35N$w?__A z>zykIv>{()S)W1F1Bt@RAVuLIkgrSgiNihbw<{x+ri$?FbfD?`M6B)4Mv_O`HLael(A(od7402|tjr)#> zg#*X!0XvY>u?DZY;lN|EXb!HK zt=N8-gFM^i>d)||`himLHVH$|ya-|lzT})Gfg`OV8zpyvS5NCmPU7i^fqX2fsbO&& zy7HX*Z;C>K`IwA!oEYh%oQ8!45SJ>nO62~I2v)$z0>t1tNL>_d#-#!va1i!BDRU>? z8$!4Mo&9Iy$T89Cn)*kx@jbP-@!~JGwL^mRcNSdO_DG_1t1Hz6ZRN}*eAFUWgi-0| ziIar&S<504mAW$(qDQVXg;8B#xHSzqgca%#JcTwqb*)UaMOg_J*To8B?rVX2kMMAZYzZE55Pt zKEbz2yeCD$o%ozr4z>lu$-H?gIl>pjKZ0Ww*L0idoIDdN{Tpm}!utE$(v8*c*;?OI zuHX%V{XI|)u(^+FR94k_Rj77KIS~J$)_ehTwhpMp)8ZhTH!eakku!@Li?9SQFDgT9y~F^cr-WviC6&ngtFpmXkJ@KhT*(hUn|xy$X61l?T^ zYR*Yi$fNs`(1_9y4=TQsLQk$JAq zHp;{WEj80He#56>t@069~=f1V_zKZn7)Hpat@80pgAve0pbv_WB^wO?uVf|0M z!C5SfZ`UF}1$!fqYO1r`k~~<9olykPo{tjHaZz1pZ}v-?ZU2+oEO}D}cqh8qet;HN zg!A~bDIP^g&EDfhiws?LD?f^V(Jp=eOYiRkPkhc|0WF6?)a0AUdOEj-O~~Njpx%bCprDnAhp8*1P&y=0Co%_$oMt$i_2HuajgF5e&KiO= zs|^s1JUthM+<}3Ei9L#Hc0*{>%seDO7}>aaLUN+KX2B($=#+uQmX z{wbciwX-u5z-`O@(0X2;?kgup*{+o=G;agY(9pE9VPjRyB6Vi&kfZo&y;fC%Xeb4- zLZlf7Ncbpzt|C)T^k{5MXrXu#})C;OB^LCoI5DGXz2YRva&f!gddBF3Mh9o};Z2n?-v`T$6b17)07rkW{TDw5^~KNpvZ zvqBY{)#j{}#5RAB2cw3p4l93Tm?JRf6PMTQzD&5~udf@Nbewvt4CA1oqc61~lm!4k ztgrXm+n{Zo>7k*B+a**&_QkFlWLo4rfW1x*lpPed?w~akHf3ZhO@_Bf&v=jEFAEn( zi>`6isR7~I2^nt z)%}yOP_=}ow~(q z+xuKjL+%BWgVGQ=Gk+=g0pv@v6kF%y2*|Z*J~7AHePhN5#lvCFX=;;u{~H}8W0LOB z%MA?4y7Db-G-J6ML86*kFa*apq~rAuTIElZ7Xq)? zURnNJFctO9H4aH=ac;d;FyL`s*3z~?uM07k0OyUNHW%bnsxdy=M}EX&Zft0)F^qUq zM5)Wrr&ZGc$BvLVRCbDE1cfoBhh}|N`FHFaT)7Q55IP}Kr(hpiC0+^JfS;p1Y_W!G zA(2H`Iup#Gf2>ZiiM3`kP^y)l$m;#wRQa@&)@8TS1U=gVM57rHNmPwhLE#lB92^{q zfz>3ZpJ2kS5bxdp;yNTGAVXwDC1c=_qzf#$83OSB=-Aj5Q66620RTahV}!ogTZ;KV zd(Ku~038O!Ba%W9bz=#>9O`#@`;Kb7t*fiLgPglM5@GjK&?c}NfbM{Hp=I~CuAW}S z*WT4SOW=4w6CmumZ|~`u!lGIAFfj`_%GwQv&cf}hBci;#kR*y$l%8&36=J+0sBCK6P3tYWNAcfUe8h1GtcoS?PzBJ76r#jyLyKvz912?OUK({RKDbLS z2(+0sG&e7V;5<&{e*Ql2Rfn7AOVA6R&-RF)H}iG*iGA>5bLFUMyZafuk(Jdj0U;o0 zhX@EusZ;eczcrVakKT3t2N*9#*{`*kcP_-t%{{IF-H!u#!uc9NM#!yu0D%H%B3sO% z)g1(cA&9HOMxPv;=ABuqVWQ=98jnH>+y8X&yspwhEt`J$*(eR?*_nBp@l&3yccvE> z(i!r!7sw#l;tl@?3i%ZQfdz0looe%pf-Xy-;{tqXAY=ie6LWz3i9-~2J;Wm9FktoC zI6Pzoh!-F)0XQ8&pF7*(djV5A2D&;z%8m)xQ?&avj>kn>&Ak<~a>WemcbG&FSSK|{ zqkPo`IVZ;nGAqDR<;jFz3q?}1{RFLAv!FYQ!@Z1`i#=`oL!Nrf!t6Ej{OoJwoM=tY z^ZbvUoZnnWgR6Pt1M~N{bDg>aGKk=kHz5U|-R1cn3c>Ca7pJGJ#A5&yaC37rH8W$H z2^cZ?-Q632K4*zma|W-WTg43)jbgu~W`?GgGA=y)7&T z@5t*y73f&pF1MvtYOfC_bt}zg`M517GMFB#fN3vDFIKlAKjB?zqV^_DPc{k&%*opd zD&1~+{lt}^fcF5Wk|My2;oqUtm;?T=aL0W_>LPwfgr`n*TLN$Ke&A z%t@D85&<2Xg0`A{CZ)$uBaPEwF+a!gxZakPm8{ihgilRUus9<@jHBg&B*4=)>J8l| z!4@N)eu9`3|400%#s`3W2N7i_h>qNdC=rnoPFc$7Zh1H`7R>T#UitnwMKU?y%W~T= zh&LSbOGm=fx281W9`@`KU-X_DUKa^$#MP!h14^y-;?apTS{oi}2GMah%i}Yd-clSx zheB<;wc+CR;`BA4=;e}>Cuk#w%-Y&nsz81&|+4(JlacUOs zZUe$L=lZ=|J7wPr*L!d9Q6kK28?$%=+fubIo1 zs%r(BAq&Ej52SsKcGy{JxP_>-by1@>@T`OM$VII37!M|6p+d#JT`7&T=hz&j%Bv-G zyc&=1K>_(%G|0eN{i>CaP*5a|r+BRI!+*ftTWn{tf9HeFYOI0Asw$V2OGi$vYvdoZ zJ#FU{DBI>*juJNyowigpDhnOpfq%}LdijfmlKjVVWFeP32`mwcYL{OY==yCB64(kyT59Qbw3 z`1{pd%RgD##5ohq7(bNii{nu2fkrR7ic=PNJli7KrihJy@;%{!7X>N%Nt94BbR~Ip zUMxgJzyrGei>L|h*Z~Sw74}y#L$m_I6dQ$W>VH0EW6M^_#qf*{%tlMwAgCNlX`3_T ztqSAlF01P;yn-?+LBXF!oxssQ7|Y_3s3+*#kEoZ*k99Nj3xS=~?rUs4b;M5-3-kl9 zQDIPnQcN;e+BS)iaisK5of;i@b_8|9^Z_H)od~39&ErN?9vg3Y1yDF+(u*ymB2K4> z-sX@tFhirHNG?KQ)exBs?7~?d8u6bp+!Lt@D<4Y$1O)ywbeo%| zo4dHyQDTIG>o5SuNgZtBbECCOc}5xU;fK%0vd?Hp)WzQ{@m*(qNig|z&EsA<6%0chn+0oI~e|hHJ-82x%SL!xb zT>qDo9Ciaq9pJc_eEk|h%5M*n@-|z7%O}hEK_=LDcv#|g3Ir%*BHj&v8BX}1lp$aY zR~+eTXuX=q;?jX#Uvw58#IuNM!U4Y#>&I}6iPB?>xQ;Le67Dxm9_lOY@k*e!n{R_^ zCvJKLFKsDTg$mm2bDOUt)Zz{|ar*0ba@HzmJfn#(PrrHT`cT(~lH;$3Hgu43D#_0| z>OjC`pUouTS{|&hhCcPl>be1G)dNjHS8ZQ}V!}GQ?J^wK(p3?BJQX z#Gb7*Pf{1SW(j-#p-g7iFMDV=J3wWGs(9-sSTkA6ik9jmOGlz+g_#DD;{PCK-{k!G z&;H$1|MvcW9ujxlb1?Gh8+IVft(_Pq`Y)3OfLUEq;>PRH0+~B_=<*BvDWFxTwa@%> zM*uYeSK-b*fkDJ=P!^PapY(1$8y=GrneoD8qwAct(Ft0u?maGzs9M6YJ7KoVd_jZlroH&UydZ(Xj&w&sP|2$Tqk(Uq0?Bdzr@JtgHat352D-s zb0F2Zq!bx}LR8Wsk$$=Ox}oApK~OqaF$QtVlglxKgXZ>3E}D9%d20+RnP zIRdE4|9@n-YnS^fQ)eWq%5jJ&rJ=8mN)f~F=tU9Ib=lRwG}A=!cU)tqy__yM^DF9| zh{EwaDtbvnU@6JiM{i+Ivn8fa_4}T?ygAcwMS6mtTH%ao_`d_*<`lSg<)O|qM~jKg zs!_oo>C18u#B%yeEo2ne$yUGJhY3-w6^^3m#DEPL|8&;73SrSrs)$%%DQFhF8Fanw z0AUvxYh@q^ffu;*DQzHn?dI`uaUv$SbyCZ02^#`(y47Vv8i=y#PR00Bsy3X6aO$%L zN>0J7^55f$B;8q)$;j&jQj7s?!RSyZg-R@?Rm{^b_jo< zbdIM1i#NqNr$ovYMi2)9yGE;HCNX_|PHb?KtB)!H(v>8Ek!tfO5?!m4LOL~jgT)X@ zJtuXY%47ocB4v96^-qsrix5PW+3RH#tJ27H!ht#Y1XL{+LX}Y@kL$b^Z&+8g2D=fj zTz11(PDGLxW8qf_u2y56fzF2%U-TqOJKp=#C4`>sZ4+7};xKU_eg!q#ubCJbf&LSL zf9pg6a$^2uG@0X(1LUa0QC(@$_7<-!CmDm5eCG#hMp8;SXhlhtb_4PAh-LU`~Da)K!UK9 zztOVKa@|qaR06z>2d5RE*#n(AmR3;CCuQ zy;J_jO8@%v^CsW_qwK50qU_#oXNGQRNs(@lmPP^T?h-{ny1NEcQo0+F?rvldP-$uD zknWI1IGgwVe&2V_bb%D@_ZQcBdrgMy-8|C+4>K9$?4#jnf79<#!k zHlZW0ILM*-%lg>5Tipr5#{BF4CG2BY98XtN;yjfdL~u4=t*9x=c$a5a@qC&^wb{J2L_!w>p$sHe;R31G%Lim&P1L=~$5SwFPY>`p%osPA0S^Z`4lk z$cfXB2GaxboZZ)%(d^A0mHin$j}9AG#QI<$G4w^oZwHGZ~5ry;CKx5c%Q7!4HXlw3esrw0&?{_uWSv-IjDehPO1?Ly6uS zVeOO{jN>`@a^2aM|TPqEoN9MdR|j-=aDk_`8C=eie#|!Y20N<` zsdOmsC1i`iVn?}ZYQt(Lfss3rV(FDg%@l#28|paqz-e{i%4xV~JFO@-PF`J;mkAtw z%#JGxnwe*lsvc9%S~1Vl6Ygp0){(?#P|##p^LB?=zJXOT?z+yIT#f}v^MNG8h~rcC zA2kUN!=%zam`q@L8ox}j=qF0jlL!m$udg#sW!g?z1{pzOa6`+Q^2P*j}=wjZ9g^$*H&-NY~Q zC%mnu^+q2MNe@AH3cXuK7wWy4wO>J&*^Cl#6N@4F2G4G`kbr}#<>9N;#`wcmrHi6=so8y zD=Q0Wa$JT%Hiom$>s7bLi!~WGq8~|^*gSyV2p`H2VZ6ph(egeqB`16!6^AahQs6AP zyR-8f>|w-GE9Yt8`Ct=yEwcpJD3|qt)Vfx`1GFz1UVE$WJ=|}8!oz$2=!Tac14kBC z#>nx`S+9`10RucL3U}uhxH5&gHlXe_gtxfukbu5nU~ur&LsYOWKn4Z|^zNRwc-;>O zI4*H`OyZmY4kpk&0Kk3H2i%VPyAdBBpQJ79zME2*o?KVTbUQo@MGNHe@ane@k%`M# zb&dd&Ck_NrckcVaKW^^s2Gtt*tFm$5zh+c^D9SmFk?6M7afAwC8FkHN9i`E_l-tki z587r?yq&A@Rfp#>QpJ@Ngwmamj+d8d_^#G}K6?)toPu^>%ysS7GWZDjq1K9Rsf6?U z+q?N2#PzNBtZk!Qrqfrggtl8VM+at;Os)eNj$A4+$<{E7J&o_j>F-;_hbl{@?@O5j zPo6FN{mWG>b1%uH1iqgl++l)?MA03PFN#k)ur4r;#CRI6#GFjr4F}X` z`n2A$V0*UBNk~*IeEk}<(|mn?;Bt5CH`@$G<-pBgr{8va>wk59ZI=xOMh?Aq^Bn;a z;4zI+ICywSj$m+vOC_vDA`Otp$H>U(sNPcsZGZsd9sqjyw zZpm6bTL7Z~pmDP^KMbO01nDrQ{VOQ)vS7PUsI?qU%Ij`tj3j5I@t10{9hMgTgB^eO zNeW^?*kjVI_;t{Saqg?=e&iS;OEx)r80ogQO6!iwGx~z_-Dt(B+X1HRLZE&xt2TL= zJx!Cx0X0A$6-b5^EFZ$MGqw(Cj*<*6W4;Puph4cS4QVSSCw9YYF5WXb`KE_N@3YbF#P!B3bz6#g1aXFpS~Ij=3~POk$-Ekut!tYBqUw zu$b;b&*L1$=k@Nz3}p{hLi8h4apXBj0keCxhk#5G7Ag0cb1se5F^y!&pY*S9uD&+; zuy`D0Ov>vBwGoh58TmO-D4n9eeU4kjM9NkKKu$Q%JDgaIwtKrBLE zu7nQrynOVK6}n6!qOBl_to*FIeVThqW--B#xqiAHvy8uI&)KJFl8#H9tK+%!DKM<;=!nAYkO(-i&GJp;XactAW zLofR=TQ{BrrH4PEVzDLe(nhPsI}!+^bxe#1roX*QDA?fref7b_GCYm3QXr-zG38gz ziYwNX@f<=oT%^bXFZqdx$BlpmX27#1|MZ&ms~!!06AVcw*HbK5OkRWqf2eQkdoMiG z;+(ks#XBe^qRi;-fT%x{K1ZYDkiu(3ph){T?Xt_DASa2o*V>iCyj=SWcF|&QbrhsPG@Y8cpDp|gJk3Atbs-GhP{}9kSk+nz znfKtst$G|7B`>??FnkGJp08x^Opebyqr)=Q7(8jAgYyx^r!#mdTk%%0V@q!Y$;aKnfU@^!8s>3e3u@eEW zMK4dUpHlx<;<#D1W3n_FY&336T()cMhcJuxJLelw7}ZA0_N<6J&acH3L#vqXwQ&PK z2vYXVD%}M{=knMCS-9BuU7j4$N9qRd>KR(H=U3?W+MOePo$!%3e9?4J$}@`2==Ogg zSZ4e0_F5HA^+~)&-BNlvO&H%+ z54Gc67#?MrhhIC^2%*oPJ(^IQ4vr^O^Cl@rc$sGZTx30K*9zOIX32|legfkwCY#wi zZ$r9B_-?6c#&xOtKM44;Oqs}@u$$JRcLZnos#$+m`anh#*2k;id6Mrt^IPl@azg~! zK3i*!fU4!B{~7P1=#WQ%CAuK*o1Z3ZF|~9A=k(eK zdte9`@(3|hXza-RBNf{B;Ud6FPSQ5-p~4{F9o-VGMZGldzLte72kIBxs@i*|#xBo( zdx#M!J@6&I&bCdJW?YX+?L%~>56>QRKUJW7!>WHRF=RGD(8>QLQp3O1+tB71i@6!K z9~bH%I+mz=pOpF9wCpLhe%T<_&T%n=_R|5J4=yW}$oid6 zmbEybv219}f;8PwU|&p}I5>NpDM?|G77!v=#OHu`6W_OZj?HU+i?$*z#OquA<{V7G zCEhXZAxe0+NS|~n4xn1bs0WWfBp@JA!$F*zHB4@G&w0~f7#)W*M7TQ8RujtXDNvKp z%+#~9i4lnu)4>^@cDPV5$L3jF(C2)EZ{^LkBkWC@;UWsQ#AsD34RA7))ZKzFgz>dz z5i9FS)mPYrLjMjiryWW*L{|3~~M~cGtl@9reb+q+UX6 zGmHsPAkWdsx>2yPlC0m+ez5;kJ7r7aA<2{(bK#G#NkX}w<+2!$|L5C_8U-m4jrUH_ z`qR-kc+cf3HaBN9 zZ8P1mI49zMx;;^IAObwc_gK3z3fNkR;NYEL+<@H46ancH`ZSqBPS5amW?Fqlh5ZB% zzo+a;QV?-Joyv+s(@YR5$>;$t)W^V8y09>GbJMnQ*8zNCz14<|_5d{l$T8REHFhev z2P|Qrk+`;|aa{h2f~5rplaLG%58Qte?luNec{9ZQW+q8z|;ZNL5c|g zW5paAv8V-kd1|ayhOPsjQVv*|M1+3w`Gff9_PDhqdl>7J@5&xr>e9*6ag4l#c7*p* zJf?vD2%g;WKhWRIZ1Dfh)Pd8rQdWQ-Z&E3{6`!Ql;_IapUKNr;wMb#S!XzP5_FGv} z3#J9w#5sh*b{ncbBd-t2^18ezQB`4|AMaOL`>rj~jWrS!Wx1m4t?ljO(|fEJW>8p! zC>|w`PjZ~x5(&I}AunBY6kkcZ{FC3%K8Lk2rS;yx2U7O10C{%rz_U>}ZU<7{ig((^ zc^ra2=OO(6vS4LqJeS;}q60t%(+@Lqbxi;=)t!1JaU~@sy&c7Wy1)Brzbzs*S^@6t zlbuvzc_tn;y)0G<=>zqXVSD}3?Np1VcOVm4!_bfdc;diJ8Y~sIx4?R`QF_wsVu!Kx zEs_HKD+tDEcHbihq5}|>Q2{hXN9S1*0n}iXP*D5^U6zjU4ftXj&a;HwFuS;gK$n$R z?9%`1Y4p~Bi8YT8$^eO|A3}_DC$Hw3@%R1PQj2-NX|JrWC+_0D=ODG$9=!1QQ{|NP zh!iMtT_#VCj+_i9-d&~UAbv_JM7pt>3OHPthi^GrWzJ!S{O(@|w-j{BfH{nah?soR zoQ3=oB)8q%hyu&wWHo3>kk0t?flML+WpZhWrna`W!DX}u2nEvC7UY|KFP*1%VmY%g z87Fvphvi6z2akXJb{?6$6mK*$u!fb~G4goFxrlF6shAVu2TrCYB_%xz>~j#{+P>2K z<>FLnIHB-ISd%{1ejdw|$R)El@HL*LWx&!lU zH001HiauganffKC*lBNOqTTIEY-v8Kx6oEz-B$azl;oO6JBxik5vty+-<%w&s00WH z$iXK*nf=}?gL=0D>n874(9Nmix21K<>|+7yM$O?n%GDMpD==-XK5mH)E>2UcV#8Rw zx0tv)tG*9oYrJ0l4;>pp_t{b?jes@f6N(-PJHL*(k*6S?12 zQeJsB$?L;3P4wnA5WLVLep){91%xx&ru#=Eelgs~n!o>>(w&bPNzZS1$wx#gklhJo z=GZQQ0Jm7K?$-X6v^2LDa@|Fh(o+PwO==d#2as&bmc-xhs@qhQPRw1-8eInOb!__W z#o+FpS#2X9FN)OQ183F{7*?|oB-`X{eIrl7 zmb+M?59MZ~KIMNnUq1I-cQ>+}e^qerGNxASY$uHwKO1TFuj)Rv(#*K>5#Kw?!oyq? zQnk|II!KZG1D_W#}CqE=`+nerWwQAH(%H~(;3 zO(~4NS(ObuUvB~HMqs}UuOc0Vu5tOJ!b{3YZxpgQeT9$RG=tA7tx?)4xUe}FVZK!P zw$fRK2IOCHbGbQQ1~tK7b!ynD<^AMvjia}4LUSd5gI?QM9nXL85NjV(Xs zn&rLafrx%95ORI z3k74w^P87qVq##s4FMGw0!pq72nyKq7#bS#HW>phaX-U2Fy*^9zJTy+o$Og)rH24U zxd)V4u*2*1h&Qew3VaqPjc#!c#}eGzV|3)jX)0{99!a9eD}kw>LFMesjGmre(ObVa z&$s@eZqw4!&Hf{e3!adi*}FHDR{(Hw@aK=~wEP+%lmXi4jc4MJq>}KTgS~jFR(vp~ z;c`i{-au)|Soy$kfQU%z_yA~pr<+|0%@e`iY}8R$Uq4Z!pbp0MQ;r~>3*;8}9UgMu z$EUfr1L-4(;udgI&aLlWXRI{iHK(C1Lsxvg@tO*K-i zXzz}XEfJNFyGk(W+TbTjb!NcHkfO8`de`FZUu)--KWg5#DtMwBIm*P58pDP1h2T2Z zBWl!L?7@a`{37;CwU{29GG;{4J*pl5VbNn|;~JLSch-hU%=^@gLBd}B!TAtZ)z_ds z5P1EmEFM*5zMl(vH;K>1&#d!fdQm_$r4QPVk!#%QuD>H6{Hh9w9OK?U2WSj5Haerw za2v&K)4lC&SkAv84m(CKU%r%Ic?CXJvbh$iHBQ$OP;@d(c>?|Ay$6koilcW`8KBlm zbJ)tSYO@C9_ls|yH6wpek=4@vLVWQAE#}Q}=d^XG97ZTG&R;oy7@q>))H)bwLqPHb zT2&>;drbK+Kbl94WI;Du`@xS`x{Uuo)LIgowac(D4B*|`ySn7wkyW2cbA{2y?UJ0^ zM#u^M2*y>0NmjB5M7!8+KCo$Y6T~_ME>FpQ!-u+RC>p=sNIfLo2Se_x>=CT0)Oc0Q z{?+vr?K%apb0?x!);$AMDr`XGu~qEqO4+N24RMbV4F#@%H}7wccfJoPPcIC@7^u$& zaAx)@jxf~u6Uh?rJU~)aYu5gw1^D>!qu!zuXu)PrfAG*w491)CV7~))JlzME9C*%O zhMRBm@>!3)5Dx0LzJ(QB#S!&cd-{OIt#N+*mSph1u_;xlo5r(NuTN_)A&+3UpYTYB zYhkoc1i8?2a$CIAhh@YHczsfnUv}nwOWHTqBqJSWwsfME&*$^XpEec;QqYeK{+QmJ zy_uZ`JdfL9%xst`HYcXfTW+NY#vrv^7_}Shd8Y z!O#e+Q7Zi9yd;<;$?NJS@1+>2ZiD0>21+n706|DV6AJ+i0|+;2(BGYJC53tT^AQkiJlN2r&99TrgEGu*yMPhg(<1y*Pb3;BZQXwH|zv> z%(RdMZ%uZK(8kwY&^;QV1pv`Sqr)PnzNRxtEiMj@)9-IMi@hPwLvWpd>LAVqOvivP z(a=V*MqzHJH6tDB2BYQWiDifX;%x} znQ*DuWdqjgLygq7+MJZu&uIFfR=7>QS|L(l<<-2y@ngq<1T7ua3c6m7P1AjKmH+KJgYi8!52g7iYCb9ajawGM{?hrjfgjXMu@KeTDh+GA z-)>HoCYnZuC7#0s#+JueB{bi^!dSxDHmAhKZcnU01@~TykEjF*K(b z?$}WqXmA}M<`_hjt6htpDwGkmnwJ!m>SEB;7Zv=BBfGrgP7UeP&*z60!Q}M;`@@X; zAMt?RpNTl{OXVdG8A|%gUu^me1W-*P#YE(sIOl^p?GnXlOkct?z9w5|n)1<>2!OtuIGxH5c6J?a^g=# z3{JNCM-sKD1=rzR^PwUVX|YeZ*FN<4MWuFnGoUKHLJBO#xiH@qu}r7hH(r3|{UB7) zl>AW6_P=QuD8=in&rZlFfq+3F=yD@PrgC(CmN_gGCFccHvzBg)W`3DJgpG1*;eEZ* z@cXYO%(s>#6!?q876G-e0`0X};(HQTw6a^JlGmNXsXOux+cT$IKAq@Xg@Y_S!!`7E z>T#5$$22sr3@(5BO(wjRExm`oB>#Me3^{(;QTKWB_cv-;u#P}|f$<_puRc%Rw&T%j zrwy0K3kSY$dfR=B*XOR`9mEIv1;5@gMZ8lRl(S$ti=f@;_S7Q8P49WWuNjw>=v(%^ zc(EWxp|1!1XP(8|#>ErdB~9vVF=Z#pIn6bt#ZewsGK=Zb!I^BN29k(3>TXr|`Pz<)kTOxxh}MBwC??yPpIG?%`6k zvRf?*Bv5{g4A?h#1oab*!9XHprDkWiGtx849616#{lE5)M#KEl2WnusW#;q&7`$eU z`bO~vb*y8H_PxO+NGv4%tCoj(RC;cVfA0c(4yYM)-KWm|OIq?{MS0W6iVcVTx!AluzV7+P&sPo=sN7#&BASiwFzrL`I{mJmfw{eYSKghdu>=^?@Ea=y4S~J-tx> zkderjhiIbS^$VZRZTK`w`H$bq9_$OBN7s5xiC^z(x(yY(sAQI0`ArFzmJF4)lv*DQ z-~K&wxbrW0Jl~@lRu=F!Q(&$&M1ud7tbglztZ4uA&!k{vmQqu`tH8qI9}D}z6XrN> zgjG<9x^;cu#yg%MESmnZ#$wb%r0sys+FiOa+2cORyz#EKBGlM|850tTP0^4fs+k|C zA3x2DZQ~zJ;J#I2Iy&JOl@hBfU3^kjDnvf|+g%`U;75WCzQre93vZ2)w+vDqPN@{5 zQ^k+&vWq&JWyQYjV@y0|7ep^5m7M7}pJ@^8=$Lq?X*LcPX#NmW0w&OC&0xjMUL-Ia6|c1 zStNT1z2WAJmt|w8O+AZk_HHT{&|vIp6Z(K4=g-QEl-r!pzN)$!snm&Fl`wRVosOyV zt9y&RLrsoTtfimK!_t+SAh1_e-Z%OKQ-jPd?;P3@lAWtJ>tvCn%{x{?owe;tg7rQ* zE!iH$DS#vrfM(8};KY2(Dt6o`&dCt?%N|vn!V}v+%N4RC4%4z&$e)Gf1lm~&_w zdf=SauyQ9Q+A;jGPWLzY`>R8dKS@gFvw2do3f|7{+#(*1!~FBFip&bDyiC8A(TPgG zmi7gKw^!Ep2D{nU{9ggQ`=loNH|Z)i8@f;$Y$GAf?fgpSoot@w_i2^j(J|(+S0-%F z#fDFS*`MU(WbQ`-?9dpufsIr=p@-Tj_~VtQ^jkcqHuL>ze@@ z8$pKq!)cyRfj$g&-);d>5XJ3FUS3|1ITx^1f7#achjVG;F!>qeCU1n9HHmbHy=~6Y z^I(8>V5YO`Cqi*bee+`zspAV*t@#yCp^eV349>Wbt%8u-Jsv!@0`Go(ZPm z=BqvO&)GVMc$Zz1A|!gas%!;vN~%+-TUa|q$tz^*O!;%8R8mqEm1pUr!hp350>W9E z>jLIm+#uk5jP}RNe;(YQ=JZJx9C~EIY1CB3H-IDrJWWdu)4(4F;p(`lIdQmGU5;`e z09mHu_tOUlfV+#$4x0|O72YyKQ7ai;y_8*=zlfb#wEx9T?Vq-c2jRm1SfFRYPd#PE zkc-b@fK$Xq9=n5NFCc5u=CYx}s$i}iA+S|lc9#Ei0k>GznsI9i7tTD7YJx2OE<5Lh zV1%V=kUL*ILbL*PybOOD!$x=^Jsu;~Aah{Q+MZSZx$5ile6a<_zl^t|5wi%HB}#vp z(5b}Oj<;?F7P||CI!HAX8vMCOrhHK{L2Huf>P0q2xv4sasv_eN-g8y2kN^$N*7mAi z`01R57?05ae^=?*`{m%XGTBwy*uQh4Q?=x3gVvG}IOJ+mB=~Px_&W5ZrQ=?K;}^bM zS+8D#j#shL7&oMhgqtLGhqiFJb!h1`#aLhHpu6!-V%hqr+76WW;ZLRE!rym@Gwmi@UoSH-(Ar8{nF!86(W)dacKNmgq-^}`L zr2D+&>HgT;i%FN|#~g((>?cY|Eq^6jL~3Q20sr6<0J#ugp@;|9DKwm&k+BLovuc9A zgd(U_x=ix#@!8iOWmjeRh^F3`OqE75S<5~6-eAxM5;?YI6BCqxA;U=6LRL5hP_R6;1!7ElU)=lNDmko7?X+VW=|pbzj~oBa zdS@|69?qB1W>+Aj62@+{K6qQe=b|Z3Hxd6Unt^=3*=RD75-+z#gvQ{p=BRAaM4kir zxwkwyzVhy4D?W24$v0x-inB2W`Rb&a^5eyC6eyHU-cu#YbScdIk{(UrVbUOZ-p)=% zU`3&06dsoMB%dPXyHV7LJrD6-$^&_`zIG__NX~Ip^?QZf2JDj>Yb`6|b@|&bqLhTR zR!YT*@3p-6irRubo-wFz1$&j_p4QmQl?$+2spUQk@sg){VD)2MB}6(zj?tojA!VRD zIycHnt70QpK(K)LLVF7p{_5sg_s-EyK}Am1bOG%nn_2QmvXH6j%MI@y=qDtmJ@fvS znn1q1GlfDjcXJuy#G)q?AA|oqkU$!uD1ma2@+1Z+wFGsG-IzZ-XL+SwW#XW;zC9SS z9nn&LHczMLqD8LhLot?1&d~;)Q^(nUVw^RQH})gXN9?c6r>vdu1?@{A#gQUchU4pP zpB5YJ^KSgu&v9zfmaR_|--AuI(p4V||C}IIiK*MHtH4jLDyF7rFjAh0hA+PMTpvfC zT=SYDK2xoyg7Yz}lo=02LgrshtuNo!`k3ii)y=|PGGmI{-zc~k(G!G8)5gmEfBvOz zsI?Vy9_LDsYZ5b6U?Y=TffmpAAeLFAylN)Nvc9&+k5>JAi9{vElr?|Hhwh?Evhy}~ zF|O-Hrn~3oR$ycN9xNoJylw$rg5SLl{|rIB9%!dCVQaP3#(Amo>`fjIK!6XJ-QnOsp#>e z?=x19lj7wNMJG8mm4@w-{+ZdotiTQ60w6lW%hFWTrFCwgWDP0Xt$ z@(knuCF31@ML9}$6SV7xDKO)9u4ZSUyv3?vuT5_nj+Q6H*-l%=9GI+UNR^v7KJQ7~ z{+{M-|NKXNm^7?F=W!x` zPMm9y46>2yGbYZ%ZK3H0;oh7C7%6cET=Ible#1V2oA3H>qLpb`4r)kKVLNLYfPf2X}o>T%U+H7l+z$Rqp+h!Tn{7V2MyW z7DDv)TU!?rPxRkE8CEcdAUaR03&i&_Q1*Jx5;4> zaN4=tW^%P1!T_wWXg(?k7oM7XbP9ej^}2ueynnL?(XF)nS>M=revO8T+61=trIvb| zDHyw0nn9yI6}a~3zm2OnWx#lXc9t#T5e2+-&R}rc?P54Aap!A#2N>L^UdMSScOW0l zbG04VW4eIB<@waW&=3!RG{AG5webWbKLc!oH1$Z-lN-Wl2&T3Un4e@fLZxY|QwR*@ z)u+0v^U^XUxVaznhXdjm>3$X+sElOw_v#d<(!oN8zqSepieDS5&paEwPM0dims8CY zCjPa8jcs%dD7ijBe?JR&hrs{`#<&pn0%jYQeaN@>ae5N8>XxN(NA0W^^=3_gCa)mT zUchqxouMhsm%TFwC~v^hEKXLP^0~+k4guQw5gIO~oVmV7I(CzPkhc`##l?ipBJw^2 zL@Mb-I~4srKZ-yVFEAO@!9)!gR`|Q;dqSV7LIQps@C1g0T{FW5TMT_A5Upynm8GAR z{3i_%R-AkHPCFpGPB2A}mD8$lQ*x?Qe9d8QB~wqK=WSAKNODIl>?%k52P~o^63rwV z{cyNCzK%B8D1GANyKFdEw270i``DgUYC9%Q4^F8t=c6d4ofF@$Q4Ku>uQ$OzX2V%` z+O(+ESo^~NS-M7vOhtV}57qM$6VQzMtnEN)glaC+^zlC9!ec9$n)B7~lntT+@An zcNWyzqVbBhrgIjoyzW6JHSo3!sG24}S^F}R8^KS=Ui|*WwwWVX`rm#L-N>j3QZ6)5 zhB3s-jq{pXubJ!xB{W@*8rp;3pVq^a89VL7iTvb-lYIffZ06hHd2dbzcJT4s^_29v zhW5r$nlr8WF%rN9vvk&3jWJ%j%H&RJe>T}2_T8T`(g7D}3QL0eZ7=i(CL%PgePr!Q z;e~-r6Gv;`+_bkR9Az#yyS9&hvxr-6{Rxk?M7+iCpxq0q=a7Xff{MWZR?FLvk9_L+ zQlR%iiSU;klk?)J8tZvgn#AaRgLiNR!iT*#vbWqd2X=Ci84Rse9jg2CVR=>{)vKUZ7QlfILo7X9>g1m3TUvaZ%*U4gX~2?$KHFxUP=Bgumns|+&}Wa zC=7A+Z4TK}`zjO8Ka_#quj++|AJYEGcSA3wa3a3_n;U}IATSz)y z;DR17?LG?+M~#?;dLL(gyY)@eSJOk1RE2}<%MXa=3&d$(2=ii*$R-W+p!cohVquoz z)|#GE5@M*%5WUPYyz({L@MPJ4OmHfi;=OgiUgDx~eCf*x%`kz9%L(bp44ZEb)@AXv ztqg!#GjDl2A0Z86RR8YRNW4`0WXbixh152b<$;mJ=c(*1bZ*j|H(!lGd{c@vPKTk3 z$$`w$9{vV3sy~q@Oyd1wU5XO(ykJJ+no91GzELx zi~5)#jOUTI$5)@zwEmI)&66kPjO{vBPaQR>77N+)3po^fGt9vE+lrvLi1@sim*qs$ zmzcb9$FS(rFcmIsjK^q2L#ys?uw13mnW?8cSDag+W`CMu%^zT;sMXoj^kJ>QISLS$$Uy5q;-dxlBpR-kB-+puudfx?+~B49srfpqayUQ2>z9FYG==A8}b8PGsxZC_^sCDIb008;f_$tBetXF37`1RIxe5HA8N z8&T7^#zZ;P$DbTEhPMzZl|L(;K!obR`9N?KkOi7SZNSzKXa~Qo`rx{&W3OB--d+R*3gFsoL zbtD#oW}tGG{w0^oIu+!*eun%y*ExuV&2epcR1u4wV^)FntA=$laU#Dj{YTMi|G_HT zEXWz`di=!V%3=xUrn{1y{mLXdkSS2==Jk6UcqPi0N57=RyvlGg#t_h@hldjIciUO+ zufAHu#BmvolL4T?*)AkW4pJ!X?KwyI_w=~(Uph?JpuhppYn-34Mr(^J>JOr>OTXbf zyo22lFKVCbNo`Xcy`!;>gq@7n#_o`-wD^ySEwMX}|2o&p{A}#KKBr0i3(1$iisGUb zaY7PGLfj;dMG3pDodM?_)*0uc5F^iBl*gwWGVuar*L*JCcB2nWTl9Ear92PVe z&+$8-G7&0)6IK^l`kx(tw0n9eVD9(#CE~#Fu0I0tlG$`n7|!sMfVcxOxt}pw;Snx8 z`8K;*V%zPrA6Q5mt&_|+I5;2n`9(!3!`sHNEC*dcQUs+Z6-qvUy1}=FK%cnL46xzG zQ*uyd*4w#WsMKxxx##zadfb%b2FnWA5O3|gW?874$XbmINe zv$#=q$6?jwV2#yNx-?MIXY^5Skr>(m#7*!dqm&r-94^`vP0bXu@fY9brHCF zgkj_1xm+Hv{i6A4-wLjlo$Ap&?P?5q7IRRd?v)#^+2CG-)@TR>NAP;=0U>k(xNb*q z{PfRiaI+cCjg3f`z;$~re;|c926_LgLrwVG60-CjiVgIP<7YqNgh?`5{B3kI%I81e z@u=gl&dYq}+o0w_`^ovE}4A+XPYlOpZv=42zegd4yIq%y% zn$l?^d^pO@KyB4oKkQ@uXml{;^1_LupiW0;W@@iOP&@ckv%DyNBL$mum5F_4Q{4YS zce=IDbFqa;xaI^b-V(7_T|G?_-*51B`B|y(nV_&N@(&{fPvGaqjYB##2{}J#QmXgq zf3yHcQcI-8Xa?i7>}=H~-c(9}tZp{Y_bPW|MT$8NQX~5`zN=T+2W8yzZ>?m{6PY|K z5H48Oihu;~;qo=6O%%U4C03t|!%{kP5s5+iej@v`Ca|8;^U>ksn<@`D7m@_tjRK*X z7Y_SVb-~u-noY;imXkO*6I(>F92*N>6A=zYpa$y%`Y^whqgW2LzHS60LhR+*Q{jUq zBy|EVjx`}$nYAxT2bS;XML-9J1nr^a_)a`R6&5hFba&dFwhiSr*N!emPc|VT z(QItJtO<%_uTq}MpcPh*HYI;ds1>;$-WKZfy_%BsNi-ppg|NFpNAh*~V*0k% z+2UX+No155GiR`j&BbEmAEhdS_XkZ;q9G5tfYz7sc5LpmTgJYNi5M`{$5 zHw#f(i^kXs%I3V}r4j^lyr-=dt{THIKS)pCGI9YCk(BlzI~!@bo%&=#L*8z)SfCaYoQ3Nx@!C-TZ1}dhV78=u0$mx2m8j~PLjP(_ zkqY!>;r?ABq66tR7B+^5)L{m(R;QU*1Eqb$*K6phIZC=peHyYtE-pL~ON-M+p{tnd zYpyrOul)T>4#Y65<9&z8w&79y2xeXjnNs;&sc{T};7jj*W%@pR9Zof=lgr`~6c*mF z-ABNX+EI1Rbl4x0!(Q~L6EDY68#(Ft)EuJOT3%Aq@@Le2VSas`Fn|B;Z%#OI57Go} zr%WsH9N8~BIWdSo(Z!RS%c4aDo)}OAE8obp7Z4Mh%VXpT_q^`&cCs(z{IRE1DxX8Y z&8@aI7gUdKQ!*SB_t%qBBG-ZJ_Urs`>GfZVrSHWXGt!g`0%p#+;6+J#)YuOndt0> zc0m;JW->@W>ZRx|OTF0V25rO`B7XbAdAp}`fJ-+aTD*)}B5TDZ3Adstwmr3T`AO&Q zio+6_3AV}E;+Ay&(u=rDsD~y?q9Yitdu4=T)B9I0 z_Mok#PkDS9=Uq&w7Xz|0;{4P#Z7U3_~&UKHb6y|%P_eHiL30Cr_W$Bd?AzWiBoR`1e zs`(*fC5h#ld}$sgw?a=jp5n;mm1sqMIC?}pOP01L*GOu|Kd(tOC$>%2^Jq*|Nk3um zJP3tFWNr?1oc3^j`%)DtTW9K4?Du8v6ZEamPAqX1w`jUX%wnihL^yrQNzXrpj;aGu+&+J?GfzZOE}c79*Yvn2GTG zY~;t-=1+NXz1@1nxm1f!qV?H}xpG$Gm+11i14ORt2l7At>e_YYUB372WT>pBlWTZH z6t1f5Y7e~6bt@G<8Z%l+imYIFplE!eJ_tFD?@RMW_NBNDT1Y$fJ0r?reHtK@h+1Gb zF@mq~^ZAp-bMw=t!5Z5^DcJiBv_aI@R~`Ak`$<)@%yLX6IKyRTpXemm?0i=xzox#~ zY(IxtmI*YP)_3&SqiE&BeO`Ppjzc^n(BpT%ZW7N{g*qsD9VElgMU3RY(6c=*s!!}v z#VkO4ke!)OYq0M_#EgSXGwQZ>zs)#W8_EUOg}N`-Z?4I9JAE~*d3!1CnL}zT7=?E` z;faR7IM<4$qDt<6I^SKj)uyC)rbQRU?C2fJUh1Fv@StxlAp0Wya3dq@E7$7_JPJKk z_okc3iP+TA)RbsKW!?AOpf36iYy+x>u+P=S7h)?+TFtBGOxWj zdiP_@**7A$rQ9+Oa4-Ur8DbNv)X0LK@OYt#_+6>-U8z!({K{7HFmrgxNAC@S4xAJD zNsc8_tQfTLA z`0$hk+0XOTSZ{f@4jKT5` z>YQ2^*%P?vBD|r33N%OP)h0Z(t4X#YEl{qFW+SQ^xLFCuOM;c;iCDS9fbfSJhiz^) zOG_Et>=u{CF5C&Az)vtPE<$$E?BTF>1Tcl1j|MDtZBrXF>$}ajz0A+(Oyld;RwB+8 zsVLC>p(7Wj>rPTNSJo{sP56VSq2*VIsa`=|IpcDs4-&=6I)JAk7f>9Uh3igx^6(^I zv;(`dO(D^7MDxI_obUDfdA@?CidMFOftGO^PogSu7~Kt2f0?;YvN@IQ_^=IiB}HVh z4`g!4+goPuuC=Hyt7_WCb66YzK z^KIq-I2L0r5on z*0>~L)He$sYeGd|Yt!@c@S4}NqH`(4odWgx`a?A)To5n2`(0ONnh#b3womR1_|u#y z;J}}|r}$Z-RCw}wrtalSO(~0*@%DLBnF3v6=6$t4D45J>DuvBVr-03fxDQJWyv0$s z1BvhQLz_XCV$AL}THN7DeABId_m)pc>wd1WhZ82F#`ypwDqKdTXv7=5k2dBpWngxp zZ|IpJ?JJJ^0bcLDVm&Ysg?Xtc=zww~M=0?|$CK%p=;(r-!$$i#>e+|V(wW{@ zC<_agx|e`M%JBuYSVWghpk#F9_&YEy!1#kSz4PT#N0Prk@CuSElqUuqg%^BCPE>9_ z-&^qRj5brOd#%0ef!f-eL1^wj&V(4Q5l&|+#OhT>Z*RL zJO4w6dBq#KVp;tlEe=-5+}!STU5A4FhjE+dy?YlRzfBi3em%o5x}S;Rm*pmggF-D5 zm>m#Iu8R{Bl%Nai=C+LMng;r%xFZ_t+D-vZ!JEs*k)a{JZbg}g$Ki5P_?+ePmP;nD z8W-=Nmv{%)xw^eI1lEt>^>2>XUI_I*lDYY688+y5Ig6^S2BOH+XIoTqltf<{HC0B0 zh5RQgkH7OXNHa;G3l!}Jqj7_?DUW?cVy_QR?BB=;=hX=4B?SBTaQkAI$lCt`es8AT z=OO5{T>+sB5RndJeHtCSXo*Bdtgo+=r(aW5fEr9TMRCbb`g8(ft*KRr6%mG z^2C5;RkMp*3ubK>ghy?&0A9&Og@=TBrP`EdyIQx_zp$C3^6gK9g~3ow!@=5d>!EPp zpfm4;rvrEg9Dd(-H%}tj%?eF<2g`Wq3l)-z8m(-2rV$=yA)SlsqOWL{EH|{IDwabK zEBA#@GwK&CknX0s)LOhk+$0IhhDO#Vg_DY_ZE=}e*J=9Tw~=x)MsW8}j9q5fOOY~5 zhhZny_Z{`&0w-3P$<-niZEP8iNiZZqRm2UWT}n@|$43!(XZ1Ajzl=-VMX28UQ4KbzHGW~ta_i9|*(;*X zj`)njNoy%DgPvkaYAsq1)1-h1oFp-g*?$5csF_^hoa;t2%_b~~YPN7($v1Mv=tH$G zuM6n5|IK+#p&FVW3RKiD?!fI0%;#+R<2PrEEGsTG$S$YOT@x}+=iL^7oA-;h2-ta# zB*t{ha>~leflmMG^<2M+A*9jw{0}TNtZr%mY$bm@y|(9gK&w}D0x$_Mr!ZAA``bez z7`*5Ys)g&!8xryADp1z46-8laE9pvZ@^-WCwZ>us>6A!ElT$hqyGTvE??;W><6oG? za^J1wF{yE-jzvD-7TRml)w$ITby@^bkGG&ZC}d$9maXJyi#ktav1JewErW;k%daqDngJyF`oS;;#IJ_w73I6G>ovi|&W#9umO`2@ zLXF5f07Fk|eMJ=GT&)cm04V4mIa}FvhEkx7wS7Rz47iu3ai=WcYqSGez z1I9_?+*ETPd@=p0jdw-8CvoDUw)FU`TOmK|{nyQlTcYsrvO=VUOo${VV{COH(gn`j zZx!#p==GQz#mh5_0@hOwb$sXm6L!|e%B91H^i@j2OO!_Tq<)IdCiIH=5WOkbKwhZ! zx4r@DQ=m?W!{UjGm^3T@-syJUWc(rIOp^}vS#xeoiIcfJG@TCM zmN7`UClFs7*^~ieb42JR?AIreFNe9LTsn%8kP_vA{jFvrRfCqpW!-MIpJTkGX@dNo zU;~z=nFrV@{pomgzm0D-k*&>$ZD2Sb1Cgm<^iT2b?xOtx14Xf34As%x;S!ZPyvUEC zq&Y6&9>3P+FkYYr+V$^=h$J+py&O#9FAhk=e-0qp7v7n7s2!vqqWDwYl7@Uhjy`M$ zLrfB5Sj$EZT%Gy*>y{cxso3~^bpzHYpqYFk6`b_jN@JEk6b`!0~;*6bVt?qhYoR_EHh4xn%LT@S1iIk-2PL&rdVM^lNUJ$4E{R&xJM+OcCfIB9bE zPV1L#v&YXqT9iEMvUbX*11U6e zebC5fI~K$lJ?H@T>FiB&uWtk5M1{x@e6U1fyi`z0#+!-n%Nd}K;d1sa>n8YDgq}A~ z9&EU%JxJ%FPKOda{?!m|2Zo>&P4&+3DOASt4hpjguYAZ(4AGyu7e34FV?QntsE%_U z_%hqnxqV4YuhQQ8#f3W!LucQYC95CY;fCwMV*)Mw#G2NIb#o5p`J^An!GEUq{g7N` z7M=i_hGPC^dj8H>t%S~)Xa{eY$W8kD~MKLA9%RsORY?&7n(2u~?OhRQ3v~+>5Oq@mbRK34~ zwNIro=dPv>b%hmS5prfL8*vG3*Bdk+~2JnVS?dV4Z zd<$N7)Ay}^jG-n&XfWx*VCbWd=7olfQ)^~vjV?Wd^^fEbbU)(Ii(qkVIyjp0e~bG%mjmLwDh4f_dy2?~RvyJ999{^+l;>Z8 zw?rh?5xyhTKiZD-Dm{MCA_9lAQb=f>QX2df`y`)U`1YWO0YVr`P6a9aNUYrY8clPeu7oTHQK4!RoEz&W5qR-4(XKw*{j#^nheQFK0ZJ#3AME4&@6s|w- znh&V0+IS^8Zp4=06}-2Mq@@b4!HYj-uq{<0J7na6%}k94!IZRP9g6zuaZS9$Wil6b zwOPy)OM9(2&ue4&X_Lm&sAFHyWCj%77Bac3?^Yv-tr|JS!MblDYu$3F3bRw>zpde% z$P&A&n2_9ucOiTmfv=oTlrEXPk`TsQxtv|-pz4cj;_d#FOO~ux7U07ou}KE6aS2Ds z-a85tFpvFSA>kaor%}a3)0<00Rd&AN#NN$KKOHc+@;P#A^T2s!CQA8XW&~bt6Lnly z$#2Zo*(+(hw(@?d5rr*(B2SrTG@9BX`tvux#_x*!!Hf?D^?bWU7%L}#3Fj?Qhmj)N zIW9d|^71;f6{d=wL>%<#{tAmdIq>4#WAPh^Wjl)tij%4mx@+CT9lr9b|9E~3^HaP} z#fc0o5AR%R2#vH^aOBxvDL8v|Me7GIZF2M`Ix)3=zxl4&y}JclD^6jv-y`eNLl9c8 z(vsE0^o>)le#JSdJr>{S3r6c6U*YKIfN@zg6J%5~rs&@E=-QEuIQG^%?-;xwf&8-0 z`=>kdxy~DQN1mLU4YPt-_IfI5LuN6%Q$9YQyu!c;v-J0qli@u-3gu%$f#A z(4)6gMSas2hfjcRrhxBaOOw7*!%fJ<*TquT2OmzFiH->?*hls1Es7~HCAJMx(&9e7 z_vy(^>O})Kb4S9y9lMYYTY3qsS8}8pt`1M83u5|GZNP1}J!g31H+Z}&xB`LR2_tTAch4`$yo3!jkm_lb?(yV4;cdnHZa-z7 zj0!fVGOGR6D^V8t)<429$lf z9+oW46xtdSeidM()1l^m7|C5d$W8>}aY;Zt;%xmTP=oTWg z1k3-a)L-8oJkz|gd^wWeBm`Q#|94Oi*+?`osB`>CA%FPdj0KTIec|)lWWeA2VzuPf zs7Xaz!A{#_VHuH4&l-H~IC#~YfJpe-Cp=SzN6t|Lb$1=1EBRz4eg3E$NiUe2`8cKx zTlayB%s4nWjJZ~oNUUp>6Q~z)JO>Qqu?~=UtGCa_Il?OevW{%K_SggK9~*xAjQ=XY z`-*7uc&%m`bxQ-eF;==d<0WSwHBx)rIwEQ&b2Op#j$x`qrxXfN!6{~N(cKQ3J~=rV z>i~u3jfbY!Y6z=1gF1#p61?;-8*{jv_4s*!T9-eL>4N}mH_68G0$QTg6yiaFOiIn+ zfM4G2$VndEa>Er#hoxO0T~V{oDgbP-|NT06ceOcHu0mRwlaurHI>bG)3ED6KyGpvX zRAa3&xF_y==K4Hf9=L$$qhG(QKAywX)g_iJmpXj6K)bpfspu?5oHKm6ElhF3@+`&s z;!aq-6~U5-^H2E-voRi%y(f8=QDvDrrMgal8I>IUnQD{y<7nEJU80st|-saca_Aiq(ABEyUkPey`R(-0%*^QTI-$D)L$gMQhE%^muMK%*?Am57noT#k z=xKSr$q5PaZ;&^6bi3@Uho*N^nV_$^)xzkHjnC;RlxGb=bP#t8^fLp0^hUbG!-svd z^{8g2p9*Wz0Ccbc2iSJDQCb~9do_)3?nw$zGN$mX z(_ZCmQ--bX_FFEsSYeyrSBKMP+Pqv=nVmBl!H;b$v?Wq5_wga)#o-eG;jqw$&{*@! z5A*gqe6ly|qjYniS7cw9zF`q1E`R@P&P;QZ_=av7mjqOhoAU5|zSwlSxLb+i;B~w- zQGqvLNoRD42EryGm1M`An#Q}=&C8Gy7o@xiE;!QdhtsU77{JoM2f0;($6Y47V0Z(H zxMAq_yeY0;$S_D_CN~tpJ#1~cTwhpOvAOQ7t=Xa_r79Ehb*S@!d=Y8?Jal-?hUXsu zqMoAZv+>6dR8--G)BLHZ1=m+%*qmUrNW$SPJ01L*TUa;-otmUeef0|5_9yPzYaV&APDE5RZp|Gu zC)DWs10fh<_pfQq*;9Dz5`?+M^$ENwH8=gPBcfQaf;zVk&wgQFU+KV)9XSRZGYCmI ztiQaD+kDs*u&WBWya4f+YeRcwAn|KGsQ7&w9qkNSa|KM>ZWEITVk;YT4Nm-*k`Ao^ zO*+p(_D01q;y}8B-ZKhoTor*8SFfDQILU~f-os&7L}3+I2G-;L2ndshmKoI~&WUqK z3_hMRA1qlM2XC{~v@~9O5i_V5B~=6Caa&pCI(xr32ZF8+>WSxh(-R_Q0pmsvLvb;Q z;AbB~DAs$%@Tc)WOL1(y?tRA>JU0GIV$)}<(Hptk=*dyYQlJ^nWgj1NYK25{eVwhW(#!B# zsgwaJW6AzzrRn?f6YWQbcxnpUto!D$cm} zVty}pF2OC2O{hGoUfXf!NA&R0s~VJ94zS#poA8_NAf+pw%zw z|IY>^jYSEcsJKfHu&xRmE-krtW*-O!Jvj$0!H+SiM~S&pyk40!gd{N~^}oC_Ye&XN z1lwX~o#W1wSP&MzkZkw++*K~hN#$xm8MB!+0| z9;MV^A*j#ChYV(@rY?{3-lvH6VSe!Qcf} ze3RQIkE&-h7c*;iidYme7?COrHfU zoxWEkD+Yt2S?QCeVsuo{9b#9m8_M~(TD-?d8jyxgUUa4imrLDD4)7!H^!3#IOde%WgLdA2qD&YlJv#|KD ztMdUIRgQPbya)UL%@O}8-fC6J<>RX_B{g3m;q$FbDyvR0jb%3iH{K@d5IN!U zN{U(RTSL(wK|Q0a-`zU6sv&Dh5DuTbz(Gav4vQ|U(W<7x*(uh^DdQb! z#Idcifzn{WU!2Z;zR(bD_9lV;O!b9i-p=2hp1d$T-!qUa{+>$-9xt+ZvPfdGmevAE+HM z_u{*sc&ssDb(Y~Xi7!`-eNskJqN{ABrUw3`^?yv%t5%hDshfWKHQ&Y~7<#BdpMd2+ zev@^ZH68Jt-ehLA!}Zna$9|U^lv{n8QJ(Utw!|m*FJRSK*jM3@4^6spQcZ7(9l0i9 z1)5#$+sz~ta!&kgfjX9rF`EaclzR;c$9_bfogYIesYt1h`?mT$XwMJqp36RS4pY|LBISs{q zk~nPNEqwXY5T5yJl;2mn!ljM!m^@JnoPWYs6dh@o1u^aBqQ7b#K8S}!*cb1SJ}=QWPGZ^7I^pn+ z4d*$pCY3CYgjT(I?uARs>6ol2Na5=)GFll=!iubKo1?C{DI^-gKLnucnFVPkisGmghfq#bB$W!}ijsflKFu9Dg>z zkwJ4H%eCcn?2FA+Gc9(SlU&2VF1kQC42Dl%Xi zT!7P^Sdnbk-A3T=lsN@KvrhO<4YEGa>$jf1#8YNL=!3XbMc40}7jmWQ*jabePv>5E zs22?z9~4X7`7>X+-tMUyR{4l;%%Y@jeHI>~M4c6rVL^ya3ryQMJw|g*i;l;obQ0-R z3(cvSck1PJ_WzgDeQJw)f-Q6-9ZTVNZMnI=qOV-*wrXQ$MrO&o5beB=wZnSKQ%zv{ zt-(t_#oa`)sf<>7bSQhl)k?g_w1N`xJf2@ay@#N#vEec!|03 ze2=rWr|F+g^{cR*aj`8wjH=Wo@NbYz*m;0=kd6zf<^+9Q#?2u( z>%@K70E4PiNiD~A!tAQqdeBG}o%nCY@?Z&=m}TdTtf=xQZpQ&Lf4UR3ixy}9@ZE;i zg6N}LBU9!{Vh@jX$|1eEKU;UanOE@sr{N7#^3eDb+$i9a!};mR)`+k0RUN~LuQ{zu z%MKHlShKO)B>vR93~4SNJLgd>ZZaXAIBc${(qbJ?s&6@o3)ou^P*sDXkA*}N4E7&a z@{ThsTqoe6pO;!PA%0XRH;>LdezR^ZzO9Nbxg{h#%}f*<(U7v-^8bj&t35Ou{&pH3 zhr;vI-Hj<4J!MCGp>K4b<^tR#HO;PfiWaMQDiSt8q8e^2paj;e{{!k-v%1|EO%PDe zC2^A0O&WWW%i1FMyB>O?gqJ6cm&1(~`(ahm;HI7LB=j0IL%5rKh#r{wddoawqiDJ5 zFyb0{v#@v5cv}1)h%ch#iqGzI+@>8m3&-EAz2oMEj`iIcp_*>1*7dDsRtm*PQa&~^ zkAl$5I?w-YcEFQbdTGMyG|hpmXvAhB_)|Qch1Y;hGr7q%_{Ew*hqWw^_8CoS)8;Hu z0o(rw=F?iwl8ZH$=Q4GBd@JwDDm=%#`1JXB@=?X3Jg(a_M0$DVlseW;m<6}|+7!c7 zkN+9ne_u-ciqr4WK0k8l?@GwVB5yG}H?O}SPwgi8lm3pkWW<^( zytG1#zu?18hvdR5c|(Mk`>Z@n0nN^%uY-Pxy+rV;d{z(ViV_6Svka&acrq5%cixr| zm9Yr+&_>{}LNqx8ftpF6HuS>c9rgl5G%h+(&y<_e6hvfk(7@i!ukMj!30uT|#k=Q+ zcb7E63vGtI%aKytnhWaMLE+uJ2ZFg~!BvzXcFR^g5b>Gy-QyLnOqWRUzH2U#trG0b zU}#x-FN&fyO~ZFB0M)&QMs`2)0~4%^&Odz$?oyeE=)jj59#zYG4KklJdp;*S;u(9c zIDV81xiz6fx!x_=i^TQi+H=H~J4P1g-kakLt=h zZmY?kqA73Qi550Eu?farTURyw}+aO^LRNgiAsBSH9((Wzly7jNpJKeViTm@DWK+`||^#Pt4 zs2r1ay#S8p$T0&G6T$UrtPp+Ce>_Y!*K6JpsJ>NzKZNg;c7t}PEB#%jV@U*3Dza1m z$o>Qs)G_NEBZVy;#Z+<$LA&(?;_39bJVsPBb9or|wp2b9!;7W)kr`QHAJVkea^qh@ z;(7LUrv*q17}Uf9XfrvQ?B-2@44HpsF+e1e7%vegVEr4rMyG_vB@wZY8wyu81C|~O zxULOg3GyPC6(yO1bVUZJpuo^NIsr@{E4@x6VQhXnI7%PZT$F2UV;0_tZ%ekP(*^HA z6-lC1x9=Q)n%A~tU@VlgPoTLb)v{- zYGD^?7kCzYVPbu60YUEl#NMM=eLgMzup-*SEBN@soAWU&)lUIx6YVAr4_UH*iekYj%g70dQiz>atVyq7=%{Q; zxAN$=`!T57>sVou*%KR501F24)AKp=dvFZ`KNLIH3Rc6L|A%hQ8IL2zn>O?P%4aZ( z5P_&sx;h2~aR`NzWEkT9!hLK~f|OX2M3!r%AHflQwA=TOp8{_(+OND;OvLbwgop@b zM4O7mvzf}i&z~P->=#-@MXTJmzTXmW0HJ~*K9+Vs zg+vl~<t4ic}OoQca`w>kCM9Kyjmqw?Xr%R?P@jnKG(nV-ISdcpWv*6R*S$(3JMApN97G{k(>#>)+hJPL7Tb^6eeE! zB&NH+&X$^};G36~0keQmuamzhwtNB!|H#$z*jp!Wumu9k7Dyst%nRze*Fb^fOJ?h% zmW88&fhxZeJ*w*H^>@yJGYGHBpOu2%S`7YHO5PuS=&E5eltnAGH}0~YtAA1r}Ma`((C zyMPDzAJs*(u!=_Z{sJiSpn$Syzl@S%<+&0MMpsv=Jr+5Dlj zQ~HDHqQ$M^RUQBfB`0=>VMxON2 z2grwKR@nbhj&ix;`l`v9L|mlYtzzcdN^b9pIJ>PrDt-JMtUdYL)(lh!1ThlMdDk#) z!w3O#-9?F`!BKQreQlX4PpD99(vu9}Ci1SyUW2&op4T8QFb@OzeWSHYsK83nUCQuT iVvc`%GZ632{zBLiV^@6tFc4yaUrO?Dxr)c;LH`HU2=FTa literal 0 HcmV?d00001 diff --git a/ecore-cocoa.pc.in b/ecore-cocoa.pc.in new file mode 100644 index 0000000..2194818 --- /dev/null +++ b/ecore-cocoa.pc.in @@ -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 index 0000000..64f6178 --- /dev/null +++ b/ecore-con.pc.in @@ -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 index 0000000..dccdee0 --- /dev/null +++ b/ecore-config.pc.in @@ -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 index 0000000..f91a8df --- /dev/null +++ b/ecore-directfb.pc.in @@ -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 index 0000000..0a21393 --- /dev/null +++ b/ecore-evas.pc.in @@ -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 index 0000000..3adc295 --- /dev/null +++ b/ecore-fb.pc.in @@ -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 index 0000000..84c10e8 --- /dev/null +++ b/ecore-file.pc.in @@ -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 index 0000000..0b160ec --- /dev/null +++ b/ecore-imf-evas.pc.in @@ -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 index 0000000..926172a --- /dev/null +++ b/ecore-imf.pc.in @@ -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 index 0000000..148060a --- /dev/null +++ b/ecore-input-evas.pc.in @@ -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 index 0000000..81d09b8 --- /dev/null +++ b/ecore-input.pc.in @@ -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 index 0000000..5b63f43 --- /dev/null +++ b/ecore-ipc.pc.in @@ -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 index 0000000..83bb7a0 --- /dev/null +++ b/ecore-job.pc.in @@ -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 index 0000000..123c8d8 --- /dev/null +++ b/ecore-sdl.pc.in @@ -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 index 0000000..b9bf64f --- /dev/null +++ b/ecore-win32.pc.in @@ -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 index 0000000..3f5bdc4 --- /dev/null +++ b/ecore-wince.pc.in @@ -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 index 0000000..454a9c3 --- /dev/null +++ b/ecore-x.pc.in @@ -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 index 0000000..87ecb6e --- /dev/null +++ b/ecore.pc.in @@ -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 index 0000000..49a4e6b --- /dev/null +++ b/ecore.spec.in @@ -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 } +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 index 0000000..0b10a6c --- /dev/null +++ b/ecore.supp @@ -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 index 0000000..c4f0b74 --- /dev/null +++ b/m4/ac_abstract_socket.m4 @@ -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 +#include +#include +#include +#include +#include +]], +[[ +// 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 index 0000000..23479a9 --- /dev/null +++ b/m4/ac_attribute.m4 @@ -0,0 +1,47 @@ +dnl Copyright (C) 2004-2008 Kim Woelders +dnl Copyright (C) 2008 Vincent Torri +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 + +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 index 0000000..a15120c --- /dev/null +++ b/m4/check_x_extension.m4 @@ -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 ] + ) + 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 index 0000000..3980e5b --- /dev/null +++ b/m4/ecore_check_module.m4 @@ -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 index 0000000..054ab0b --- /dev/null +++ b/m4/ecore_check_options.m4 @@ -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 + #include + ], + [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 index 0000000..d83ed68 --- /dev/null +++ b/m4/efl_doxygen.m4 @@ -0,0 +1,97 @@ +dnl Copyright (C) 2008 Vincent Torri +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 index 0000000..f57bfd2 --- /dev/null +++ b/m4/efl_path_max.m4 @@ -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 , 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 + ]], + [[ +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 index 0000000..1894ad7 --- /dev/null +++ b/m4/efl_pthread.m4 @@ -0,0 +1,130 @@ +dnl Copyright (C) 2010 Vincent Torri +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_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_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 index 0000000..3a4dfe2 --- /dev/null +++ b/m4/efl_tests.m4 @@ -0,0 +1,43 @@ +dnl Copyright (C) 2008 Vincent Torri +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 index 0000000..e69de29 diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..770fcb6 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +cs de el fr it + diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..22837ab --- /dev/null +++ b/po/Makevars @@ -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 index 0000000..5014aa2 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1 @@ +src/lib/ecore/ecore_getopt.c diff --git a/po/cs.po b/po/cs.po new file mode 100644 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 \n" +"Language-Team: cs \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 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 , 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 \n" +"Language-Team: German \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 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 , 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 \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 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 , 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 \n" +"Language-Team: Enlightenment French Team \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 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 , 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 \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 index 0000000..282522d --- /dev/null +++ b/src/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..a6fc38f --- /dev/null +++ b/src/Makefile.am @@ -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 index 0000000..79fccac --- /dev/null +++ b/src/bin/.cvsignore @@ -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 index 0000000..bf59b69 --- /dev/null +++ b/src/bin/Makefile.am @@ -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 index 0000000..8bf2988 --- /dev/null +++ b/src/bin/ecore_config.c @@ -0,0 +1,324 @@ +#include "config.h" +#include "Ecore.h" + +#include +#include +#include + +#ifdef BUILD_ECORE_CONFIG +#include +#include +#include +#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 \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 index 0000000..282522d --- /dev/null +++ b/src/lib/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 0000000..0c00c6a --- /dev/null +++ b/src/lib/Makefile.am @@ -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 index 0000000..78de274 --- /dev/null +++ b/src/lib/ecore/.cvsignore @@ -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 index 0000000..48dea7b --- /dev/null +++ b/src/lib/ecore/Ecore.h @@ -0,0 +1,357 @@ +#ifndef _ECORE_H +#define _ECORE_H + +#ifdef _MSC_VER +# include +#endif + +#include + +#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 +#elif (defined (__FreeBSD__) && (__FreeBSD_version >= 420001)) || defined (__OpenBSD__) +# include +# include +#else +# include +# include +#endif + +#include + +#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 index 0000000..a36c7a0 --- /dev/null +++ b/src/lib/ecore/Ecore_Getopt.h @@ -0,0 +1,403 @@ +#ifndef _ECORE_GETOPT_H +#define _ECORE_GETOPT_H + +#include +#include + +#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 index 0000000..c1fb716 --- /dev/null +++ b/src/lib/ecore/Makefile.am @@ -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 index 0000000..8ccb8d2 --- /dev/null +++ b/src/lib/ecore/ecore.c @@ -0,0 +1,417 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +# include +#endif + +#ifdef HAVE_LOCALE_H +# include +#endif + +#ifdef HAVE_LANGINFO_H +# include +#endif + +#ifdef HAVE_SYS_MMAN_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif +#include + +#include "Ecore.h" +#include "ecore_private.h" + +#if HAVE_MALLINFO +#include + +#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 + * + * 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 ""; + }; +} + +/* 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 index 0000000..96aa844 --- /dev/null +++ b/src/lib/ecore/ecore_anim.c @@ -0,0 +1,237 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..4e2b63e --- /dev/null +++ b/src/lib/ecore/ecore_app.c @@ -0,0 +1,81 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifndef _MSC_VER +# include +#else +# include +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..e30234d --- /dev/null +++ b/src/lib/ecore/ecore_events.c @@ -0,0 +1,630 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..3366fa6 --- /dev/null +++ b/src/lib/ecore/ecore_exe.c @@ -0,0 +1,1850 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_WAIT_H +# include +#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 index 0000000..b27c57f --- /dev/null +++ b/src/lib/ecore/ecore_exe_win32.c @@ -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 +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#include "Ecore.h" +#include "ecore_private.h" + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#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, ¤t_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 index 0000000..2b2e60a --- /dev/null +++ b/src/lib/ecore/ecore_exe_wince.c @@ -0,0 +1,24 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..af18922 --- /dev/null +++ b/src/lib/ecore/ecore_getopt.c @@ -0,0 +1,1739 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +#endif + +#include +#include +#include +#include + +#ifdef ENABLE_NLS +# include +#else +# define gettext(x) (x) +# define dgettext(domain, x) (x) +#endif + +#define _(x) dgettext("ecore", x) + +#ifdef _WIN32_WCE +# include +#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 index 0000000..0b1a39c --- /dev/null +++ b/src/lib/ecore/ecore_glib.c @@ -0,0 +1,290 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "Ecore.h" +#include "ecore_private.h" + +#ifdef HAVE_GLIB +#include + +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 index 0000000..2f9a592 --- /dev/null +++ b/src/lib/ecore/ecore_idle_enterer.c @@ -0,0 +1,171 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..1d5c6ce --- /dev/null +++ b/src/lib/ecore/ecore_idle_exiter.c @@ -0,0 +1,148 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..6df9ad0 --- /dev/null +++ b/src/lib/ecore/ecore_idler.c @@ -0,0 +1,154 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..0557a69 --- /dev/null +++ b/src/lib/ecore/ecore_job.c @@ -0,0 +1,110 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..7c53bfd --- /dev/null +++ b/src/lib/ecore/ecore_main.c @@ -0,0 +1,1076 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +# ifndef USER_TIMER_MINIMUM +# define USER_TIMER_MINIMUM 0x0a +# endif +#endif + +#ifdef __SUNPRO_C +# include +# include +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +# include +#else +# include +#endif + +#define FIX_HZ 1 + +#ifdef FIX_HZ +# ifndef _MSC_VER +# include +# endif +# ifndef HZ +# define HZ 100 +# endif +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..0eea8ce --- /dev/null +++ b/src/lib/ecore/ecore_pipe.c @@ -0,0 +1,600 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#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 + +# 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 +# include + +# 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 + * #include + * + * 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 index 0000000..09ae899 --- /dev/null +++ b/src/lib/ecore/ecore_poll.c @@ -0,0 +1,370 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..ea59794 --- /dev/null +++ b/src/lib/ecore/ecore_private.h @@ -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 index 0000000..5d0ddb5 --- /dev/null +++ b/src/lib/ecore/ecore_signal.c @@ -0,0 +1,624 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +#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 index 0000000..8c62db4 --- /dev/null +++ b/src/lib/ecore/ecore_thread.c @@ -0,0 +1,323 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#ifdef EFL_HAVE_PTHREAD +# include +#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 index 0000000..70abb26 --- /dev/null +++ b/src/lib/ecore/ecore_time.c @@ -0,0 +1,72 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef HAVE_SYS_TIME_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..8d13c06 --- /dev/null +++ b/src/lib/ecore/ecore_timer.c @@ -0,0 +1,581 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..a3a11fd --- /dev/null +++ b/src/lib/ecore_cocoa/Ecore_Cocoa.h @@ -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 index 0000000..cafd503 --- /dev/null +++ b/src/lib/ecore_cocoa/Ecore_Cocoa_Keys.h @@ -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 index 0000000..190d0fa --- /dev/null +++ b/src/lib/ecore_cocoa/Makefile.am @@ -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 index 0000000..ad2e767 --- /dev/null +++ b/src/lib/ecore_cocoa/ecore_cocoa.m @@ -0,0 +1,280 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include + +#include +#include +#include + +#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 index 0000000..05bdc1f --- /dev/null +++ b/src/lib/ecore_cocoa/ecore_cocoa_private.h @@ -0,0 +1,13 @@ +#ifndef _ECORE_COCOA_PRIVATE_H +#define _ECORE_COCOA_PRIVATE_H + + +struct _Ecore_Cocoa_Window +{ + NSWindow *window; + + unsigned int borderless : 1; +}; + + +#endif diff --git a/src/lib/ecore_cocoa/ecore_cocoa_window.m b/src/lib/ecore_cocoa/ecore_cocoa_window.m new file mode 100644 index 0000000..751bde4 --- /dev/null +++ b/src/lib/ecore_cocoa/ecore_cocoa_window.m @@ -0,0 +1,110 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "Ecore_Cocoa.h" + +Ecore_Cocoa_Window * +ecore_cocoa_window_new(int x, + int y, + int width, + int height) +{ + NSWindow *window; + + window = [[NSWindow alloc] + initWithContentRect:NSMakeRect(x, y, width, height) + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSResizableWindowMask | + NSMiniaturizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO + screen:nil + ]; + if (!window) + return NULL; + + return window; +} + +void +ecore_cocoa_window_free(Ecore_Cocoa_Window *window) +{ + if (!window) + return; + + [window release]; +} + +void +ecore_cocoa_window_move(Ecore_Cocoa_Window *window, + int x, + int y) +{ + if (!window) + return; +} + +void +ecore_cocoa_window_resize(Ecore_Cocoa_Window *window, + int width, + int height) +{ + if (!window) + return; + + [window setContentSize: NSMakeSize(width, height)]; +} + +void +ecore_cocoa_window_move_resize(Ecore_Cocoa_Window *window, + int x, + int y, + int width, + int height) +{ + if (!window) + return; +} + +void +ecore_cocoa_window_title_set(Ecore_Cocoa_Window *window, const char *title) +{ + if (!window || !title) + return; + + [window setTitle:[NSString stringWithUTF8String:title]]; +} + +void +ecore_cocoa_window_show(Ecore_Cocoa_Window *window) +{ + if (!window || [window isVisible]) + return; + + [window orderFront:NSApp]; +} + +void +ecore_cocoa_window_hide(Ecore_Cocoa_Window *window) +{ + if (!window || ![window isVisible]) + return; + + [window orderOut:NSApp]; +} + +void +ecore_cocoa_window_borderless_set(Ecore_Cocoa_Window *window, + int on) +{ + if (!window) + return; + + if (on) + [window setContentBorderThickness:0.0 + forEdje:NSMinXEdge | NSMinYEdge | NSMaxXEdge | NSMaxYEdge]; +} diff --git a/src/lib/ecore_con/.cvsignore b/src/lib/ecore_con/.cvsignore new file mode 100644 index 0000000..310b663 --- /dev/null +++ b/src/lib/ecore_con/.cvsignore @@ -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 index 0000000..7061f9f --- /dev/null +++ b/src/lib/ecore_con/Ecore_Con.h @@ -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 +#include +#ifdef _WIN32 +# include +#else +# include +#endif +#include + +#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 index 0000000..a4ba20b --- /dev/null +++ b/src/lib/ecore_con/Makefile.am @@ -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 index 0000000..5a912e8 --- /dev/null +++ b/src/lib/ecore_con/ecore_con.c @@ -0,0 +1,1698 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef HAVE_NETINET_TCP_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..a6f2430 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_ares.c @@ -0,0 +1,484 @@ +#ifdef HAVE_CONFIG_H +# include +#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 +#include +#include + +#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 index 0000000..4a0ff99 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_info.c @@ -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 +#endif + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +#endif + +#include +#include +#include +#include +#ifdef __OpenBSD__ +# include +#endif + +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef HAVE_ARPA_NAMESER_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#ifdef HAVE_NETDB_H +# include +#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 index 0000000..20cb224 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_local.c @@ -0,0 +1,254 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#ifdef HAVE_SYS_UN_H +# include +#endif + +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#include +#include + +#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 index 0000000..ce106fa --- /dev/null +++ b/src/lib/ecore_con/ecore_con_private.h @@ -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 +#elif USE_OPENSSL +# include +#endif +#ifdef HAVE_CURL +#include +#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 index 0000000..6be7214 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_ssl.c @@ -0,0 +1,776 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if USE_GNUTLS +# include +#elif USE_OPENSSL +# include +#endif + +#ifdef HAVE_WS2TCPIP_H +# include +#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 index 0000000..4590939 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_url.c @@ -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 +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_WS2TCPIP_H +# include +#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 index 0000000..59bc827 --- /dev/null +++ b/src/lib/ecore_config/.cvsignore @@ -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 index 0000000..6733d7b --- /dev/null +++ b/src/lib/ecore_config/Ecore_Config.h @@ -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 + +# 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 index 0000000..9ac305f --- /dev/null +++ b/src/lib/ecore_config/Makefile.am @@ -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 index 0000000..88ed306 --- /dev/null +++ b/src/lib/ecore_config/ecore_config.c @@ -0,0 +1,1873 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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(""); + 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 index 0000000..bb5e12a --- /dev/null +++ b/src/lib/ecore_config/ecore_config_db.c @@ -0,0 +1,300 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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 index 0000000..10d22a6 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_extra.c @@ -0,0 +1,807 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#include + +#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//themes|~/.e/apps//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[] = + { " ", " ", " ", " ", " ", " ", "" }; + +/** + * 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 index 0000000..7b3dea1 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_ipc.h @@ -0,0 +1,50 @@ +#include +#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 index 0000000..a36efe3 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_ipc_ecore.c @@ -0,0 +1,388 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* by Azundris, with thanks to Corey Donohoe */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "ecore_private.h" +#include + +#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 index 0000000..edb7ed1 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_ipc_main.c @@ -0,0 +1,280 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* ############## bad */ +#define HAVE_EVAS2 + +#include +#include +#include +#include +#include +#include +#include +#include /* 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(""); +} + +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(""); +} + +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(""); + + 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 : ""); +} + +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 index 0000000..b97f695 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_private.h @@ -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 index 0000000..e2c54df --- /dev/null +++ b/src/lib/ecore_config/ecore_config_storage.c @@ -0,0 +1,180 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 index 0000000..4f1658c --- /dev/null +++ b/src/lib/ecore_config/ecore_config_util.c @@ -0,0 +1,133 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* azundris */ + +#include +#include /* malloc(), free() */ +#include +#include /* str...() */ + +#include /* 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 index 0000000..5bee9d6 --- /dev/null +++ b/src/lib/ecore_config/ecore_config_util.h @@ -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 index 0000000..ce9e988 --- /dev/null +++ b/src/lib/ecore_directfb/.cvsignore @@ -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 index 0000000..abb2ee8 --- /dev/null +++ b/src/lib/ecore_directfb/Ecore_DirectFB.h @@ -0,0 +1,191 @@ +#ifndef _ECORE_DIRECTFB_H +#define _ECORE_DIRECTFB_H + +#include + +#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 index 0000000..d270ae2 --- /dev/null +++ b/src/lib/ecore_directfb/Makefile.am @@ -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 index 0000000..2b6c44d --- /dev/null +++ b/src/lib/ecore_directfb/ecore_directfb.c @@ -0,0 +1,731 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..9b2c96f --- /dev/null +++ b/src/lib/ecore_directfb/ecore_directfb_keys.h @@ -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 index 0000000..e9124aa --- /dev/null +++ b/src/lib/ecore_directfb/ecore_directfb_private.h @@ -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 index 0000000..09980ae --- /dev/null +++ b/src/lib/ecore_evas/.cvsignore @@ -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 index 0000000..a113bdb --- /dev/null +++ b/src/lib/ecore_evas/Ecore_Evas.h @@ -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 +#include + +#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 + +/* 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 index 0000000..adabce7 --- /dev/null +++ b/src/lib/ecore_evas/Makefile.am @@ -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 index 0000000..eda08f3 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas.c @@ -0,0 +1,2860 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifndef _MSC_VER +# include +#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 index 0000000..0e194a4 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_buffer.c @@ -0,0 +1,712 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include "ecore_private.h" +#include + +#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 index 0000000..f1b3445 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_cocoa.c @@ -0,0 +1,465 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef BUILD_ECORE_EVAS_COCOA +#import +#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 index 0000000..46e81c9 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_directfb.c @@ -0,0 +1,577 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include "ecore_private.h" +#ifdef BUILD_ECORE_EVAS_DIRECTFB +#include +#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 index 0000000..3280589 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_fb.c @@ -0,0 +1,674 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include "ecore_private.h" +#ifdef BUILD_ECORE_EVAS_FB +#include +#include +#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 index 0000000..24b027d --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_private.h @@ -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 +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_MMAN_H +# include +#endif + +#include +#include +#include +#include + +#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 +# ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB +# include +# endif +# ifdef BUILD_ECORE_EVAS_XRENDER_XCB +# include +# include +# endif +# endif +# ifdef HAVE_ECORE_X_XLIB +# include +# include +# ifdef BUILD_ECORE_EVAS_SOFTWARE_XLIB +# include +# endif +# ifdef BUILD_ECORE_EVAS_XRENDER_X11 +# include +# include +# endif +# ifdef BUILD_ECORE_EVAS_OPENGL_X11 +# include +# endif +# ifdef BUILD_ECORE_EVAS_SOFTWARE_16_X11 +# include +# endif +# endif +#endif + +#ifdef BUILD_ECORE_EVAS_FB +# include +#endif + +#ifdef BUILD_ECORE_EVAS_DIRECTFB +# include +# include "Ecore_DirectFB.h" +#endif + +#ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER +# include +#endif + +#ifdef BUILD_ECORE_EVAS_WIN32 +# include "Ecore_Win32.h" +# ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI +# include +# endif +# ifdef BUILD_ECORE_EVAS_SOFTWARE_DDRAW +# include +# endif +# ifdef BUILD_ECORE_EVAS_DIRECT3D +# include +# endif +# ifdef BUILD_ECORE_EVAS_OPENGL_GLEW +# include +# endif +# ifdef BUILD_ECORE_EVAS_SOFTWARE_16_DDRAW +# include +# endif +#endif + +#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE +# include "Ecore_WinCE.h" +# include +#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 index 0000000..153c87e --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_sdl.c @@ -0,0 +1,512 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL) +# include +# ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL +# include +# endif +# ifdef BUILD_ECORE_EVAS_OPENGL_SDL +# include +# 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 index 0000000..3caa6a4 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_util.c @@ -0,0 +1,488 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#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 index 0000000..69ab158 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_win32.c @@ -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 /* for NULL */ + +#include +#include "ecore_private.h" +#ifdef BUILD_ECORE_EVAS_WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +# include +# include +#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 index 0000000..d283302 --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_wince.c @@ -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 /* for NULL */ + +#include +#include "ecore_private.h" +#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +# include +# include +#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 index 0000000..ff5a36e --- /dev/null +++ b/src/lib/ecore_evas/ecore_evas_x.c @@ -0,0 +1,3764 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#ifdef BUILD_ECORE_EVAS_X11 +# include +# include +#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 index 0000000..6ff5cc5 --- /dev/null +++ b/src/lib/ecore_fb/.cvsignore @@ -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 index 0000000..5374817 --- /dev/null +++ b/src/lib/ecore_fb/Ecore_Fb.h @@ -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 index 0000000..2d82071 --- /dev/null +++ b/src/lib/ecore_fb/Makefile.am @@ -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 index 0000000..acc380a --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb.c @@ -0,0 +1,113 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..0cc1186 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_kbd.c @@ -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 index 0000000..ff03497 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_keytable.h @@ -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 index 0000000..c0e80eb --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_li.c @@ -0,0 +1,572 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..121f69e --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_private.h @@ -0,0 +1,82 @@ +#ifndef _ECORE_FB_PRIVATE_H +#define _ECORE_FB_PRIVATE_H + +#include "Ecore.h" +#include "ecore_private.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 + #undef kernel_ulong_t + #undef BITS_PER_LONG +#else + #include +#endif + +#include +#include +#include + +/* 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 */ +#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 index 0000000..3a062da --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_ps2.c @@ -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 index 0000000..cb9eff6 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_ts.c @@ -0,0 +1,316 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_TSLIB +# include +# include +#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 index 0000000..972aa9b --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_vt.c @@ -0,0 +1,290 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..be74149 --- /dev/null +++ b/src/lib/ecore_file/.cvsignore @@ -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 index 0000000..144117d --- /dev/null +++ b/src/lib/ecore_file/Ecore_File.h @@ -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 + +#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 index 0000000..fff3591 --- /dev/null +++ b/src/lib/ecore_file/Makefile.am @@ -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 index 0000000..385307a --- /dev/null +++ b/src/lib/ecore_file/ecore_file.c @@ -0,0 +1,941 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +# include +# include +#endif + +#ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +#endif + +#ifdef HAVE_FEATURES_H +# include +#endif +#include +#include + +#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 index 0000000..94682c5 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_download.c @@ -0,0 +1,315 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..72a2496 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_monitor.c @@ -0,0 +1,146 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..bc2c111 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_monitor_inotify.c @@ -0,0 +1,351 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#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 +#else +# include +# include +#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 index 0000000..07b0a88 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_monitor_poll.c @@ -0,0 +1,343 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..c9992c5 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_monitor_win32.c @@ -0,0 +1,310 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_NOTIFY_WIN32 + +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +# include + +# include "ecore_file_private.h" + + +typedef struct _Ecore_File_Monitor_Win32 Ecore_File_Monitor_Win32; +typedef struct _Ecore_File_Monitor_Win32_Data Ecore_File_Monitor_Win32_Data; + +/* 4096 = 256 * sizeof(FILE_NOTIFY_INFORMATION) */ +# define ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE 4096 +# define ECORE_FILE_MONITOR_WIN32(x) ((Ecore_File_Monitor_Win32 *)(x)) + +struct _Ecore_File_Monitor_Win32_Data +{ + char buffer[ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE]; + OVERLAPPED overlapped; + HANDLE handle; + HANDLE event; + Ecore_File_Monitor *monitor; + Ecore_Win32_Handler *h; + DWORD buf_length; + int is_dir; +}; + +struct _Ecore_File_Monitor_Win32 +{ + Ecore_File_Monitor monitor; + Ecore_File_Monitor_Win32_Data *file; + Ecore_File_Monitor_Win32_Data *dir; +}; + +static Ecore_File_Monitor *_monitors = NULL; + +static int _ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh); + + +static Ecore_File_Monitor_Win32_Data * +_ecore_file_monitor_win32_data_new(Ecore_File_Monitor *monitor, int type) +{ + Ecore_File_Monitor_Win32_Data *md; + DWORD filter; + + md = (Ecore_File_Monitor_Win32_Data *)calloc(1, sizeof(Ecore_File_Monitor_Win32_Data)); + if (!md) return NULL; + + md->handle = CreateFile(monitor->path, + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | + FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OVERLAPPED, + NULL); + if (md->handle == INVALID_HANDLE_VALUE) + goto free_md; + + md->event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!md->event) + goto close_handle; + + ZeroMemory (&md->overlapped, sizeof(md->overlapped)); + md->overlapped.hEvent = md->event; + + filter = (type == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME; + filter |= + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_SECURITY; + + if (!ReadDirectoryChangesW(md->handle, + md->buffer, + ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE, + FALSE, + filter, + &md->buf_length, + &md->overlapped, + NULL)) + goto close_event; + + md->h = ecore_main_win32_handler_add(md->event, + _ecore_file_monitor_win32_cb, + md); + if (!md->h) + goto close_event; + + md->monitor = monitor; + md->is_dir = type; + + return md; + + close_event: + CloseHandle(md->event); + close_handle: + CloseHandle(md->handle); + free_md: + free(md); + + return NULL; +} + +static void +_ecore_file_monitor_win32_data_free(Ecore_File_Monitor_Win32_Data *md) +{ + if (!md) return; + + CloseHandle(md->event); + CloseHandle (md->handle); + free (md); +} + +static int +_ecore_file_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh) +{ + char filename[PATH_MAX]; + PFILE_NOTIFY_INFORMATION fni; + Ecore_File_Monitor_Win32_Data *md; + wchar_t *wname; + char *name; + DWORD filter; + DWORD offset; + DWORD buf_length; + Ecore_File_Event event = ECORE_FILE_EVENT_NONE; + + md = (Ecore_File_Monitor_Win32_Data *)data; + + if (!GetOverlappedResult (md->handle, &md->overlapped, &buf_length, TRUE)) + return 1; + + fni = (PFILE_NOTIFY_INFORMATION)md->buffer; + do { + if (!fni) + break; + offset = fni->NextEntryOffset; + + wname = (wchar_t *)malloc(sizeof(wchar_t) * (fni->FileNameLength + 1)); + if (!wname) + return 0; + + memcpy(wname, fni->FileName, fni->FileNameLength); + wname[fni->FileNameLength]='\0'; + name = evil_wchar_to_char(wname); + free(wname); + if (!name) + return 0; + + _snprintf(filename, PATH_MAX, "%s\\%s", md->monitor->path, name); + free(name); + + switch (fni->Action) + { + case FILE_ACTION_ADDED: + if (md->is_dir) + event = ECORE_FILE_EVENT_CREATED_DIRECTORY; + else + event = ECORE_FILE_EVENT_CREATED_FILE; + break; + case FILE_ACTION_REMOVED: + if (md->is_dir) + event = ECORE_FILE_EVENT_DELETED_DIRECTORY; + else + event = ECORE_FILE_EVENT_DELETED_FILE; + break; + case FILE_ACTION_MODIFIED: + if (!md->is_dir) + event = ECORE_FILE_EVENT_MODIFIED; + break; + case FILE_ACTION_RENAMED_OLD_NAME: + if (md->is_dir) + event = ECORE_FILE_EVENT_DELETED_DIRECTORY; + else + event = ECORE_FILE_EVENT_DELETED_FILE; + break; + case FILE_ACTION_RENAMED_NEW_NAME: + if (md->is_dir) + event = ECORE_FILE_EVENT_CREATED_DIRECTORY; + else + event = ECORE_FILE_EVENT_CREATED_FILE; + break; + default: + fprintf(stderr, "unknown event\n"); + event = ECORE_FILE_EVENT_NONE; + break; + } + if (event != ECORE_FILE_EVENT_NONE) + md->monitor->func(md->monitor->data, md->monitor, event, filename); + + fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset); + } while (offset); + + filter = (md->is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME; + filter |= + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_SECURITY; + + ReadDirectoryChangesW(md->handle, + md->buffer, + ECORE_FILE_MONITOR_WIN32_BUFFER_SIZE, + FALSE, + filter, + &md->buf_length, + &md->overlapped, + NULL); + return 1; +} + +int +ecore_file_monitor_win32_init(void) +{ + return 1; +} + +int +ecore_file_monitor_win32_shutdown(void) +{ + return 1; +} + +Ecore_File_Monitor * +ecore_file_monitor_win32_add(const char *path, + void (*func) (void *data, Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + Ecore_File_Monitor_Win32 *m; + Ecore_File_Monitor *em; + size_t len; + + if (!path || (*path == '\0')) return NULL; + if (!ecore_file_exists(path) || !ecore_file_is_dir(path)) + return NULL; + if (!func) return NULL; + + em = (Ecore_File_Monitor *)calloc(1, sizeof(Ecore_File_Monitor_Win32)); + if (!em) return NULL; + + em->func = func; + em->data = data; + + em->path = strdup(path); + if (!em->path) + { + free(em); + return NULL; + } + len = strlen(em->path); + if (em->path[len - 1] == '/' || em->path[len - 1] == '\\') + em->path[len - 1] = '\0'; + + m = ECORE_FILE_MONITOR_WIN32(em); + + m->file = _ecore_file_monitor_win32_data_new(em, 0); + if (!m->file) + { + free(em->path); + free(em); + return NULL; + } + + m->dir = _ecore_file_monitor_win32_data_new(em, 1); + if (!m->dir) + { + _ecore_file_monitor_win32_data_free(m->file); + free(em->path); + free(em); + return NULL; + } + + _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em))); + + return em; +} + +void +ecore_file_monitor_win32_del(Ecore_File_Monitor *em) +{ + Ecore_File_Monitor_Win32 *m; + + if (!em) + return; + + m = ECORE_FILE_MONITOR_WIN32(em); + _ecore_file_monitor_win32_data_free(m->dir); + _ecore_file_monitor_win32_data_free(m->file); + free(em->path); + free(em); +} + +#endif diff --git a/src/lib/ecore_file/ecore_file_path.c b/src/lib/ecore_file/ecore_file_path.c new file mode 100644 index 0000000..2e66074 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_path.c @@ -0,0 +1,138 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..0729872 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_private.h @@ -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 +#endif + +#ifdef HAVE_EVIL +# include +#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 index 0000000..09980ae --- /dev/null +++ b/src/lib/ecore_imf/.cvsignore @@ -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 index 0000000..d75a521 --- /dev/null +++ b/src/lib/ecore_imf/Ecore_IMF.h @@ -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 + +#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 index 0000000..385ae8c --- /dev/null +++ b/src/lib/ecore_imf/Makefile.am @@ -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 index 0000000..e3b2915 --- /dev/null +++ b/src/lib/ecore_imf/ecore_imf.c @@ -0,0 +1,80 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..1214be0 --- /dev/null +++ b/src/lib/ecore_imf/ecore_imf_context.c @@ -0,0 +1,807 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#include + +#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 index 0000000..0bf24f8 --- /dev/null +++ b/src/lib/ecore_imf/ecore_imf_module.c @@ -0,0 +1,215 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#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 index 0000000..23b8301 --- /dev/null +++ b/src/lib/ecore_imf/ecore_imf_private.h @@ -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 index 0000000..09980ae --- /dev/null +++ b/src/lib/ecore_imf_evas/.cvsignore @@ -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 index 0000000..ea99324 --- /dev/null +++ b/src/lib/ecore_imf_evas/Ecore_IMF_Evas.h @@ -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 +#include + +#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 index 0000000..2455944 --- /dev/null +++ b/src/lib/ecore_imf_evas/Makefile.am @@ -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 index 0000000..b14f5dd --- /dev/null +++ b/src/lib/ecore_imf_evas/ecore_imf_evas.c @@ -0,0 +1,263 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..883e300 --- /dev/null +++ b/src/lib/ecore_input/Ecore_Input.h @@ -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 index 0000000..4a666c2 --- /dev/null +++ b/src/lib/ecore_input/Makefile.am @@ -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 index 0000000..448772e --- /dev/null +++ b/src/lib/ecore_input/ecore_input.c @@ -0,0 +1,123 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..5660a20 --- /dev/null +++ b/src/lib/ecore_input/ecore_input_private.h @@ -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 index 0000000..265d611 --- /dev/null +++ b/src/lib/ecore_input_evas/Ecore_Input_Evas.h @@ -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 + +#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 index 0000000..b0fe622 --- /dev/null +++ b/src/lib/ecore_input_evas/Makefile.am @@ -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 index 0000000..15664da --- /dev/null +++ b/src/lib/ecore_input_evas/ecore_input_evas.c @@ -0,0 +1,353 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..c19cfbf --- /dev/null +++ b/src/lib/ecore_input_evas/ecore_input_evas_private.h @@ -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 index 0000000..f98e6f6 --- /dev/null +++ b/src/lib/ecore_ipc/.cvsignore @@ -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 index 0000000..41392ee --- /dev/null +++ b/src/lib/ecore_ipc/Ecore_Ipc.h @@ -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 index 0000000..6b3f186 --- /dev/null +++ b/src/lib/ecore_ipc/Makefile.am @@ -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 index 0000000..5753789 --- /dev/null +++ b/src/lib/ecore_ipc/ecore_ipc.c @@ -0,0 +1,1588 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef HAVE_NETINET_IN_H +# include +# include +#endif + +#ifdef HAVE_WINSOCK2_H +# include +#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 index 0000000..b46f62b --- /dev/null +++ b/src/lib/ecore_ipc/ecore_ipc_private.h @@ -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 +#elif USE_OPENSSL +# include +#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 index 0000000..09980ae --- /dev/null +++ b/src/lib/ecore_sdl/.cvsignore @@ -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 index 0000000..ea81358 --- /dev/null +++ b/src/lib/ecore_sdl/Ecore_Sdl.h @@ -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 index 0000000..e1bc430 --- /dev/null +++ b/src/lib/ecore_sdl/Ecore_Sdl_Keys.h @@ -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 index 0000000..2e434ef --- /dev/null +++ b/src/lib/ecore_sdl/Makefile.am @@ -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 index 0000000..fc98c99 --- /dev/null +++ b/src/lib/ecore_sdl/ecore_sdl.c @@ -0,0 +1,315 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 + +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 index 0000000..37e9570 --- /dev/null +++ b/src/lib/ecore_sdl/ecore_sdl_private.h @@ -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 index 0000000..6607302 --- /dev/null +++ b/src/lib/ecore_win32/.cvsignore @@ -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 index 0000000..6b310d3 --- /dev/null +++ b/src/lib/ecore_win32/Ecore_Win32.h @@ -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 index 0000000..015f302 --- /dev/null +++ b/src/lib/ecore_win32/Makefile.am @@ -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 index 0000000..eb70763 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32.c @@ -0,0 +1,454 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include /* for printf */ + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +#include "Ecore_Win32.h" +#include "ecore_win32_private.h" + + +/* OLE IID for Drag'n Drop */ + +# define INITGUID +# include +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 index 0000000..5979e76 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_cursor.c @@ -0,0 +1,133 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include + +#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 index 0000000..25363b2 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd.c @@ -0,0 +1,133 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..6de1035 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp @@ -0,0 +1,209 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#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 index 0000000..3d289cf --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_data_object.h @@ -0,0 +1,49 @@ +#ifndef __ECORE_WIN32_DND_DATA_OBJECT_H__ +#define __ECORE_WIN32_DND_DATA_OBJECT_H__ + + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + + +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 index 0000000..065ac6a --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_drop_source.cpp @@ -0,0 +1,92 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..9081f46 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_drop_source.h @@ -0,0 +1,36 @@ +#ifndef __ECORE_WIN32_DND_DROP_SOURCE_H__ +#define __ECORE_WIN32_DND_DROP_SOURCE_H__ + + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#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 index 0000000..5051316 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_drop_target.cpp @@ -0,0 +1,232 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..24c3de3 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_drop_target.h @@ -0,0 +1,47 @@ +#ifndef __ECORE_WIN32_DND_DROP_TARGET_H__ +#define __ECORE_WIN32_DND_DROP_TARGET_H__ + + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#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 index 0000000..a3858bc --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp @@ -0,0 +1,157 @@ + +#include + +#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 index 0000000..9f17f56 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.h @@ -0,0 +1,50 @@ +#ifndef __ECORE_WIN32_DND_ENUMFORMATETC_H__ +#define __ECORE_WIN32_DND_ENUMFORMATETC_H__ + + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + + +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 index 0000000..3d57095 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_event.c @@ -0,0 +1,1014 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include /* for printf */ + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +#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 index 0000000..e824dac --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_private.h @@ -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 index 0000000..618b516 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_window.c @@ -0,0 +1,1217 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include /* for printf */ + +#define _WIN32_WINNT 0x0500 // For WS_EX_LAYERED + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include + +#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 index 0000000..584f554 --- /dev/null +++ b/src/lib/ecore_wince/.cvsignore @@ -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 index 0000000..30fe6b0 --- /dev/null +++ b/src/lib/ecore_wince/Ecore_WinCE.h @@ -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 index 0000000..2ea84f6 --- /dev/null +++ b/src/lib/ecore_wince/Makefile.am @@ -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 index 0000000..c507471 --- /dev/null +++ b/src/lib/ecore_wince/ecore_wince.c @@ -0,0 +1,363 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include /* for printf */ + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include +#include +#include + +#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 index 0000000..f61f5f9 --- /dev/null +++ b/src/lib/ecore_wince/ecore_wince_event.c @@ -0,0 +1,917 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include +#include +#include + +#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 index 0000000..09a2f0d --- /dev/null +++ b/src/lib/ecore_wince/ecore_wince_private.h @@ -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 index 0000000..cf6b23f --- /dev/null +++ b/src/lib/ecore_wince/ecore_wince_window.c @@ -0,0 +1,596 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include +#include + +#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 index 0000000..8728e80 --- /dev/null +++ b/src/lib/ecore_x/.cvsignore @@ -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 index 0000000..a8fe707 --- /dev/null +++ b/src/lib/ecore_x/Ecore_X.h @@ -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 + +#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 + +/** + * @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 +#include + +#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 index 0000000..02d9905 --- /dev/null +++ b/src/lib/ecore_x/Ecore_X_Atoms.h @@ -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 index 0000000..af2e97a --- /dev/null +++ b/src/lib/ecore_x/Ecore_X_Cursor.h @@ -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 index 0000000..1286b37 --- /dev/null +++ b/src/lib/ecore_x/Makefile.am @@ -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 index 0000000..fd7e9b6 --- /dev/null +++ b/src/lib/ecore_x/ecore_x_atoms_decl.h @@ -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 index 0000000..5fba3e8 --- /dev/null +++ b/src/lib/ecore_x/xcb/.cvsignore @@ -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 index 0000000..81152ad --- /dev/null +++ b/src/lib/ecore_x/xcb/Makefile.am @@ -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 index 0000000..7f1a63e --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb.c @@ -0,0 +1,1975 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#include + +#include +#include + +#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 index 0000000..fa5bf24 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_atom.c @@ -0,0 +1,483 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#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 index 0000000..e2c9a21 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_composite.c @@ -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 index 0000000..1dcea4d --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_cursor.c @@ -0,0 +1,270 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include +#include + + +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 index 0000000..6e104b3 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_damage.c @@ -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 = + * 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 index 0000000..dfa5562 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_dnd.c @@ -0,0 +1,773 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#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 index 0000000..cb61d45 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_dpms.c @@ -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 index 0000000..75b6911 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_drawable.c @@ -0,0 +1,150 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include + + +/** + * @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 index 0000000..4c82617 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_e.c @@ -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 index 0000000..94d2c5c --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_events.c @@ -0,0 +1,2168 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#include + +#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 index 0000000..d4014d4 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_fixes.c @@ -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 index 0000000..83d019b --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_gc.c @@ -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 index 0000000..b356cf2 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_icccm.c @@ -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 +#include +#include + +#include + +#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 index 0000000..f96c4cf --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_mwm.c @@ -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 index 0000000..e9a76e5 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_netwm.c @@ -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 +#include + +#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-" */ + 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 index 0000000..11a7675 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c @@ -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 index 0000000..0416ea0 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_private.h @@ -0,0 +1,363 @@ +#ifndef __ECORE_XCB_PRIVATE_H__ +#define __ECORE_XCB_PRIVATE_H__ + +#include "config.h" + +#include + +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +#ifndef XK_MISCELLANY +# define XK_MISCELLANY 1 +#endif /* XK_MISCELLANY */ + +#include +#include +#include +#include +#ifdef ECORE_XCB_CURSOR +# include +#endif /* ECORE_XCB_CURSOR */ +#ifdef ECORE_XCB_DAMAGE +# include +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_COMPOSITE +# include +#endif /* ECORE_XCB_COMPOSITE */ +#ifdef ECORE_XCB_DPMS +# include +#endif /* ECORE_XCB_DPMS */ +#ifdef ECORE_XCB_RANDR +# include +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_RENDER +# include +#endif /* ECORE_XCB_RENDER */ +#ifdef ECORE_XCB_SCREENSAVER +# include +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE +# include +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC +# include +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_XFIXES +# include +#endif /* ECORE_XCB_XFIXES */ +#ifdef ECORE_XCB_XINERAMA +# include +#endif /* ECORE_XCB_XINERAMA */ +#ifdef ECORE_XCB_XPRINT +# include +#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 index 0000000..60ef77f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_randr.c @@ -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 index 0000000..24d27a1 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_region.c @@ -0,0 +1,170 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..c9ec11e --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_reply.c @@ -0,0 +1,115 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + + +/* + * 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 index 0000000..9dc13a6 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c @@ -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 index 0000000..d329add --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_selection.c @@ -0,0 +1,1064 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#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 index 0000000..c0f2486 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_shape.c @@ -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 index 0000000..d3a22dd --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_sync.c @@ -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 index 0000000..44c27b7 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window.c @@ -0,0 +1,2024 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#include + +#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 index 0000000..3fc3d17 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c @@ -0,0 +1,879 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include +#include + +#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 index 0000000..c025673 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c @@ -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 index 0000000..52aaf96 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c @@ -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 index 0000000..39b336e --- /dev/null +++ b/src/lib/ecore_x/xlib/.cvsignore @@ -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 index 0000000..0757df4 --- /dev/null +++ b/src/lib/ecore_x/xlib/Makefile.am @@ -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 index 0000000..547b7ba --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x.c @@ -0,0 +1,1722 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +//#define LOGRT 1 + +#ifdef LOGRT +#include +#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 index 0000000..c7b2ea2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_atoms.c @@ -0,0 +1,324 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +#endif + +#include + +#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 index 0000000..617f0fb --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_composite.c @@ -0,0 +1,154 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..82c50a0 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_cursor.c @@ -0,0 +1,238 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..05695ec --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_damage.c @@ -0,0 +1,72 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..1caeb25 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_dnd.c @@ -0,0 +1,608 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..3b15dbc --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_dpms.c @@ -0,0 +1,244 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..91d7959 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_drawable.c @@ -0,0 +1,107 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..5493ca4 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_e.c @@ -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 +#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 index 0000000..ccf3822 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_error.c @@ -0,0 +1,105 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..a30f610 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_events.c @@ -0,0 +1,2137 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include + +#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 index 0000000..ce2d19d --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_fixes.c @@ -0,0 +1,293 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..7f527e7 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_gc.c @@ -0,0 +1,149 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..5afaab4 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_icccm.c @@ -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 +#endif + +#include +#include + +#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 index 0000000..aaa4ba0 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_image.c @@ -0,0 +1,274 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +#include +#include +#include +#include +#include + +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 index 0000000..d580da9 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_mwm.c @@ -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 +#endif + +#include + +#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 index 0000000..363c886 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_netwm.c @@ -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 +#endif + +#include +#include + +#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-" */ + 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 index 0000000..5c69770 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_pixmap.c @@ -0,0 +1,107 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..484a7f2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_private.h @@ -0,0 +1,308 @@ +#ifndef _ECORE_X_PRIVATE_H +#define _ECORE_X_PRIVATE_H + +#include +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define XK_MISCELLANY 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ECORE_XCURSOR +#include +#endif +#ifdef ECORE_XPRINT +#include +#endif +#ifdef ECORE_XINERAMA +#include +#endif +#ifdef ECORE_XRANDR +#include +#endif +#ifdef ECORE_XSS +#include +#endif +#ifdef ECORE_XRENDER +#include +#endif +#ifdef ECORE_XFIXES +#include +#endif +#ifdef ECORE_XCOMPOSITE +#include +#endif +#ifdef ECORE_XDAMAGE +#include +#endif +#ifdef ECORE_XDPMS +#include +#endif +#ifdef ECORE_XKB +#include +#endif +#ifdef ECORE_XI2 +#include +#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 index 0000000..185c04f --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr.c @@ -0,0 +1,308 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..eb2345d --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_region.c @@ -0,0 +1,143 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..dcb718a --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_screensaver.c @@ -0,0 +1,160 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * Screensaver code + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..3f5ff2e --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_selection.c @@ -0,0 +1,834 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..451ce98 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_sync.c @@ -0,0 +1,119 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * XSync code + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..415b6a2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_test.c @@ -0,0 +1,131 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef ECORE_XTEST +# include +#endif + +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include + + +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 index 0000000..2067def --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window.c @@ -0,0 +1,1463 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#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 index 0000000..cf81c3c --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window_prop.c @@ -0,0 +1,687 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" +#include +#include + +#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 index 0000000..c6c0314 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window_shape.c @@ -0,0 +1,212 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..5812728 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_xi2.c @@ -0,0 +1,163 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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 index 0000000..cb6c8db --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_xinerama.c @@ -0,0 +1,68 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * Xinerama code + */ + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..005e1c9 --- /dev/null +++ b/src/tests/Makefile.am @@ -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 index 0000000..9c7e199 --- /dev/null +++ b/src/tests/ecore_suite.c @@ -0,0 +1,102 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#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 index 0000000..2e35ee7 --- /dev/null +++ b/src/tests/ecore_suite.h @@ -0,0 +1,10 @@ +#ifndef _ECORE_SUITE_H +#define _ECORE_SUITE_H + +#include + +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 index 0000000..fc0c668 --- /dev/null +++ b/src/tests/ecore_test_ecore.c @@ -0,0 +1,241 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#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 index 0000000..3eba612 --- /dev/null +++ b/src/tests/ecore_test_ecore_con.c @@ -0,0 +1,25 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#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); +} -- 2.7.4