From: Youmin Ha Date: Tue, 18 May 2010 07:15:55 +0000 (+0900) Subject: svn update: 48958 (latest:48959) X-Git-Tag: 2.0_alpha~376 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9cda093342ba5334cf3a2ec854323bc48a7a4eae;p=framework%2Fuifw%2Fecore.git svn update: 48958 (latest:48959) --- 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 0000000..d42aeb4 Binary files /dev/null and b/doc/img/e.png differ diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css new file mode 100644 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 0000000..7975489 Binary files /dev/null and b/doc/img/elementary.png differ diff --git a/doc/img/foot_bg.png b/doc/img/foot_bg.png new file mode 100644 index 0000000..b24f3a4 Binary files /dev/null and b/doc/img/foot_bg.png differ diff --git a/doc/img/head_bg.png b/doc/img/head_bg.png new file mode 100644 index 0000000..081dc13 Binary files /dev/null and b/doc/img/head_bg.png differ diff --git a/doc/img/header_menu_background.png b/doc/img/header_menu_background.png new file mode 100644 index 0000000..e978743 Binary files /dev/null and b/doc/img/header_menu_background.png differ diff --git a/doc/img/header_menu_background_last.png b/doc/img/header_menu_background_last.png new file mode 100644 index 0000000..88c116c Binary files /dev/null and b/doc/img/header_menu_background_last.png differ diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png new file mode 100644 index 0000000..de97c92 Binary files /dev/null and b/doc/img/header_menu_current_background.png differ diff --git a/doc/img/header_menu_unselected_background.png b/doc/img/header_menu_unselected_background.png new file mode 100644 index 0000000..50e5fd8 Binary files /dev/null and b/doc/img/header_menu_unselected_background.png differ diff --git a/doc/img/logo.png b/doc/img/logo.png new file mode 100644 index 0000000..b3884a5 Binary files /dev/null and b/doc/img/logo.png differ diff --git a/doc/img/prog_flow.png b/doc/img/prog_flow.png new file mode 100644 index 0000000..06c89c1 Binary files /dev/null and b/doc/img/prog_flow.png differ diff --git a/ecore-cocoa.pc.in b/ecore-cocoa.pc.in new file mode 100644 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); +}