--- /dev/null
+Copyright notice for Enlightenment:
+
+Copyright (C) 2000-2012 Carsten Haitzler and various contributors (see AUTHORS)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+#maintainer-clean removes everything
+MAINTAINERCLEANFILES = aclocal.m4 compile config.sub config.guess config.h.in \
+ configure depcomp install-sh ltmain.sh Makefile.in missing
+
+SUBDIRS = src
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
--- /dev/null
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+#rm -rf autom4te.cache
+#rm -f aclocal.m4 ltmain.sh
+
+#echo "Running autoreconf..." ; autoreconf -v --install || exit 1
+#echo "Running configure..." ; ./configure --enable-maintainer-mode
+
+set -x
+aclocal
+autoconf
+libtoolize --copy --force
+autoheader
+automake --foreign --add-missing --copy
+
--- /dev/null
+# Process this file with autoconf to produce a configure script.
+dnl Process this file with autoconf to produce a configure script.
+
+# Note )
+#
+# AC_DEFINE(VARIABLE, VALUE, DESCRIPTION)
+# output the following to config.h
+# /* DESCRIPTION */
+# #define VARIABLE VALUE
+#
+# AC_SUBST(VARIABLE, [VALUE])
+# define $(VARIABLE) as VALUE in Makefile
+
+dnl ========================================================================
+# initialization
+dnl ========================================================================
+AC_INIT([e-mod-tizen-gesture], [0.1], [jhyuni.kang@samsung.com])
+
+# check for tools needed by automake generated Makefiles
+# -Wall : Turn all warnings on.
+# -Werror: report warings as errors.
+# foreign: relax some GNU standard requirements
+#AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+dnl ========================================================================
+# checks for programs
+dnl ========================================================================
+AC_PROG_CC
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+
+dnl ========================================================================
+# checks for libraries
+dnl ========================================================================
+
+dnl ========================================================================
+# checks for header files
+dnl ========================================================================
+#AC_HEADER_STDC
+AC_CHECK_HEADERS([math.h fcntl.h stdlib.h string.h unistd.h])
+
+dnl ========================================================================
+# checks for input files
+dnl ========================================================================
+
+dnl ========================================================================
+# checks for typedefs, structures, and compiler characteristics
+AC_C_CONST
+
+dnl ========================================================================
+# checks for library functions
+dnl ========================================================================
+#AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_CHECK_FUNCS([memset munmap strcasecmp strdup])
+
+dnl ========================================================================
+# checks for pkg-config
+dnl ========================================================================
+PKG_PROG_PKG_CONFIG
+
+dnl ========================================================================
+# checks for pkg-config
+dnl ========================================================================
+PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment,
+ dlog])
+ENLIGHTENMENT_CFLAGS="${ENLIGHTENMENT_CFLAGS} -D_GNU_SOURCE "
+AC_SUBST(ENLIGHTENMENT_CFLAGS)
+AC_SUBST(ENLIGHTENMENT_LIBS)
+
+# Find edje_cc
+#PKG_CHECK_MODULES(EDJE, [edje >= 0.5.0])
+#AC_ARG_WITH(edje-cc,
+# AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc]),
+# [
+# v=$withval;
+# EDJE_CC=$v
+# ],
+# [
+# EDJE_CC=$(pkg-config --variable=prefix edje)/bin/edje_cc
+# ]
+#)
+#AC_SUBST(EDJE_CC)
+#AC_MSG_CHECKING([Which edje_cc to use])
+#AC_MSG_RESULT(${EDJE_CC})
+
+dnl ========================================================================
+# checks for wayland only argument
+dnl ========================================================================
+have_wayland_only=no
+AC_ARG_ENABLE([wayland-only],
+ AS_HELP_STRING([--enable-wayland-only],[enable wayland-only version of enlightenment @<:@default=disabled@:>@]),
+ [have_wayland_only=$enableval],
+ [have_wayland_only=no])
+AC_MSG_CHECKING([whether wayland-only version is enabled])
+AM_CONDITIONAL(WAYLAND_ONLY, test x$have_wayland_only = xyes)
+if test "x${have_wayland_only}" != "xno"; then
+ AC_DEFINE_UNQUOTED([HAVE_WAYLAND_ONLY],[1],[enable wayland-only version of enlightenment])
+fi
+
+# to include e_comp_wl.h
+if test "x${have_wayland_only}" != "xno"; then
+ AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support])
+fi
+
+dnl ========================================================================
+# checks for wayland only argument
+dnl ========================================================================
+if test "x${have_wayland_only}" = "xyes"; then
+ PKG_CHECK_MODULES(WAYLAND, [wayland-server, tizen-extension-server])
+fi
+
+release=$(pkg-config --variable=release enlightenment)
+MODULE_ARCH="$host_os-$host_cpu-$release"
+AC_SUBST(MODULE_ARCH)
+AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
+
+datadir=$(pkg-config --variable=modules enlightenment)/${PACKAGE}
+AC_ARG_ENABLE(homedir-install,
+ AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]),
+ [ datadir="${HOME}/.e/e/modules/${PACKAGE}" ]
+)
+
+dnl ========================================================================
+# output files
+dnl ========================================================================
+
+# create HEADER for all HEADER.in.
+# HEADERS contain definitions made with AC_DEFINE.
+# the following command will create config.h from config.h.in
+AC_CONFIG_HEADERS([config.h])
+
+# create FILE for all FILE.in.
+# FILES contains definitions made with AC_SUBST.
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ ])
+
+AC_OUTPUT
+
+
--- /dev/null
+%bcond_with x
+%bcond_with wayland
+
+Name: e-mod-tizen-gesture
+Version: 0.1.0
+Release: 1
+Summary: The Enlightenment Gesture Module for Tizen
+URL: http://www.enlightenment.org
+Group: Graphics & UI Framework/Other
+Source0: %{name}-%{version}.tar.gz
+License: BSD-2-Clause
+BuildRequires: pkgconfig(enlightenment)
+BuildRequires: gettext
+BuildRequires: pkgconfig(wayland-server)
+BuildRequires: pkgconfig(tizen-extension-server)
+BuildRequires: pkgconfig(dlog)
+
+%global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share}
+
+%description
+This package is a the Enlightenment Gesture Module for Tizen.
+
+%prep
+%setup -q
+
+%build
+
+export GC_SECTIONS_FLAGS="-fdata-sections -ffunction-sections -Wl,--gc-sections"
+export CFLAGS+=" -Wall -g -fPIC -rdynamic ${GC_SECTIONS_FLAGS} -DE_LOGGING=1 "
+export LDFLAGS+=" -Wl,--hash-style=both -Wl,--as-needed -Wl,--rpath=/usr/lib"
+
+%autogen
+%configure --prefix=/usr \
+ --enable-wayland-only \
+make
+
+%install
+rm -rf %{buildroot}
+
+# for license notification
+mkdir -p %{buildroot}/%{TZ_SYS_RO_SHARE}/license
+cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/%{TZ_SYS_RO_SHARE}/license/%{name}
+
+# install
+make install DESTDIR=%{buildroot}
+
+# clear useless textual files
+find %{buildroot}%{_libdir}/enlightenment/modules/%{name} -name *.la | xargs rm
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/enlightenment/modules/e-mod-tizen-gesture
+/%{TZ_SYS_RO_SHARE}/license/%{name}
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+MODULE = e-mod-tizen-gesture
+
+LDFLAGS +=
+
+pkgdir = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+module_la_SOURCES = e_mod_main.c \
+ e_mod_main.h \
+ e_mod_gesture_events.c
+module_la_CFLAGS = @ENLIGHTENMENT_CFLAGS@ @WAYLAND_CFLAGS@ -DHAVE_WAYLAND_ONLY
+module_la_LDFLAGS = -module -avoid-version @WAYLAND_LIBS@ @ENLIGHTENMENT_LIBS@
+
+module_la_DEPENDENCIES = $(top_builddir)/config.h
--- /dev/null
+#define E_COMP_WL
+#include "e_mod_main.h"
+#include <string.h>
+
+static void
+_e_gesture_swipe_cancel(void)
+{
+ E_Gesture_Event_Swipe *swipes = &gesture->gesture_events.swipes;
+
+ if (swipes->start_timer)
+ {
+ ecore_timer_del(swipes->start_timer);
+ swipes->start_timer = NULL;
+ }
+ if (swipes->done_timer)
+ {
+ ecore_timer_del(swipes->done_timer);
+ swipes->done_timer = NULL;
+ }
+
+ swipes->enabled_finger = 0x0;
+ swipes->direction = E_GESTURE_DIRECTION_NONE;
+
+ gesture->gesture_filter |= TIZEN_GESTURE_TYPE_SWIPE;
+}
+
+static Eina_Bool
+_e_gesture_is_touch_device(const char *identifier)
+{
+ Eina_List *l;
+ char *data;
+
+ EINA_LIST_FOREACH(gesture->touch_devices, l, data)
+ {
+ if (!strncmp(data, identifier, strlen(identifier)))
+ {
+ return EINA_TRUE;
+ }
+ }
+ return EINA_FALSE;
+}
+
+static void
+_e_gesture_send_swipe(int fingers, int x, int y, int direction, struct wl_client *client, struct wl_resource *res)
+{
+ enum tizen_gesture_direction dir = 0;
+ Ecore_Event_Mouse_Button *ev_cancel;
+ switch (direction)
+ {
+ case E_GESTURE_DIRECTION_DOWN:
+ dir = TIZEN_GESTURE_DIRECTION_DOWN;
+ break;
+ case E_GESTURE_DIRECTION_LEFT:
+ dir = TIZEN_GESTURE_DIRECTION_LEFT;
+ break;
+ case E_GESTURE_DIRECTION_UP:
+ dir = TIZEN_GESTURE_DIRECTION_UP;
+ break;
+ case E_GESTURE_DIRECTION_RIGHT:
+ dir = TIZEN_GESTURE_DIRECTION_RIGHT;
+ break;
+ }
+
+ ev_cancel = E_NEW(Ecore_Event_Mouse_Button, 1);
+ EINA_SAFETY_ON_NULL_RETURN(ev_cancel);
+
+ ev_cancel->timestamp = (int)(ecore_time_get()*1000);
+ ev_cancel->same_screen = 1;
+
+ ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_CANCEL, ev_cancel, NULL, NULL);
+
+ GTINF("Send swipe gesture (direction: %d) to client: %p\n", dir, client);
+
+ tizen_gesture_send_swipe(res, fingers, TIZEN_GESTURE_MODE_DONE, x, y, dir);
+ _e_gesture_swipe_cancel();
+
+ gesture->gesture_events.recognized_gesture |= TIZEN_GESTURE_TYPE_SWIPE;
+}
+
+static Eina_Bool
+_e_gesture_process_device_add(void *event)
+{
+ Ecore_Event_Device_Info *ev = event;
+
+ if (ev->caps & EVDEV_SEAT_TOUCH)
+ {
+ gesture->touch_devices = eina_list_append(gesture->touch_devices, ev->identifier);
+ GTINF("%s(%s) device is touch device: add list\n", ev->name, ev->identifier);
+ }
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_gesture_process_device_del(void *event)
+{
+ Ecore_Event_Device_Info *ev = event;
+ Eina_List *l, *l_next;
+ char *data;
+
+ if (ev->caps & EVDEV_SEAT_TOUCH)
+ {
+ EINA_LIST_FOREACH_SAFE(gesture->touch_devices, l, l_next, data)
+ {
+ if (!strncmp(data, ev->identifier, strlen(ev->identifier)))
+ {
+ GTINF("%s(%s) device is touch device: remove list\n", ev->name, ev->identifier);
+ gesture->touch_devices = eina_list_remove(gesture->touch_devices, data);
+ E_FREE(data);
+ }
+ }
+ }
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_gesture_timer_swipe_start(void *data)
+{
+ E_Gesture_Event_Swipe *swipes = &gesture->gesture_events.swipes;
+ int idx = gesture->gesture_events.num_pressed;
+ int i;
+
+ GTDBG("Swipe start timer is expired. Currently alived swipe fingers: 0x%x\n", swipes->enabled_finger);
+
+ for (i = E_GESTURE_FINGER_MAX; i > idx; i--)
+ {
+ swipes->enabled_finger &= ~(1 << i);
+ }
+ if ((swipes->direction == E_GESTURE_DIRECTION_DOWN && !swipes->fingers[idx].direction[E_GESTURE_DIRECTION_DOWN].client) ||
+ (swipes->direction == E_GESTURE_DIRECTION_LEFT && !swipes->fingers[idx].direction[E_GESTURE_DIRECTION_LEFT].client) ||
+ (swipes->direction == E_GESTURE_DIRECTION_UP && !swipes->fingers[idx].direction[E_GESTURE_DIRECTION_UP].client) ||
+ (swipes->direction == E_GESTURE_DIRECTION_RIGHT && !swipes->fingers[idx].direction[E_GESTURE_DIRECTION_RIGHT].client))
+ {
+ _e_gesture_swipe_cancel();
+ }
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_e_gesture_timer_swipe_done(void *data)
+{
+ E_Gesture_Event_Swipe *swipes = &gesture->gesture_events.swipes;
+
+ GTDBG("Swipe done timer is expired. Currently alived swipe fingers: 0x%x\n", swipes->enabled_finger);
+
+ _e_gesture_swipe_cancel();
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_e_gesture_process_swipe_down(Ecore_Event_Mouse_Button *ev)
+{
+ E_Gesture_Event_Swipe *swipes = &gesture->gesture_events.swipes;
+ int i;
+ unsigned int idx = ev->multi.device+1;
+
+ if (gesture->gesture_events.num_pressed == 1)
+ {
+ for (i = 0; i < E_GESTURE_FINGER_MAX+1; i++)
+ {
+ if (swipes->fingers[i].enabled)
+ {
+ swipes->enabled_finger |= (1 << i);
+ }
+ }
+
+ if (ev->y < E_GESTURE_SWIPE_START_AREA)
+ swipes->direction = E_GESTURE_DIRECTION_DOWN;
+ else if (ev->y > e_comp->h - E_GESTURE_SWIPE_START_AREA)
+ swipes->direction = E_GESTURE_DIRECTION_UP;
+ else if (ev->x < E_GESTURE_SWIPE_START_AREA)
+ swipes->direction = E_GESTURE_DIRECTION_RIGHT;
+ else if (ev->x > e_comp->w - E_GESTURE_SWIPE_START_AREA)
+ swipes->direction = E_GESTURE_DIRECTION_LEFT;
+
+ if (swipes->direction != E_GESTURE_DIRECTION_DOWN &&
+ !((swipes->combined_keycode == E_GESTURE_SWIPE_COMBINE_KEY) && swipes->direction == E_GESTURE_DIRECTION_RIGHT))
+ {
+ _e_gesture_swipe_cancel();
+ }
+ else
+ {
+ swipes->fingers[idx].start.x = ev->x;
+ swipes->fingers[idx].start.y = ev->y;
+ swipes->start_timer = ecore_timer_add(E_GESTURE_SWIPE_START_TIME, _e_gesture_timer_swipe_start, NULL);
+ swipes->done_timer = ecore_timer_add(E_GESTURE_SWIPE_DONE_TIME, _e_gesture_timer_swipe_done, NULL);
+ }
+ }
+ else
+ {
+ swipes->enabled_finger &= ~(1 << (gesture->gesture_events.num_pressed - 1));
+ if (swipes->start_timer == NULL)
+ {
+ _e_gesture_swipe_cancel();
+ }
+ }
+}
+
+static void
+_e_gesture_process_swipe_move(Ecore_Event_Mouse_Move *ev)
+{
+ E_Gesture_Event_Swipe *swipes = &gesture->gesture_events.swipes;
+ Coords diff;
+ unsigned int idx = ev->multi.device+1;
+
+ if (!(swipes->enabled_finger & (1 << idx)))
+ return;
+
+ diff.x = ABS(swipes->fingers[idx].start.x - ev->x);
+ diff.y = ABS(swipes->fingers[idx].start.y - ev->y);
+
+ switch(swipes->direction)
+ {
+ case E_GESTURE_DIRECTION_DOWN:
+ if (diff.x > E_GESTURE_SWIPE_DIFF_FAIL)
+ {
+ _e_gesture_swipe_cancel();
+ break;
+ }
+ if (diff.y > E_GESTURE_SWIPE_DIFF_SUCCESS)
+ {
+ _e_gesture_send_swipe(idx, swipes->fingers[idx].start.x, swipes->fingers[idx].start.y, swipes->direction, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_DOWN].client, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_DOWN].res);
+ }
+ break;
+ case E_GESTURE_DIRECTION_LEFT:
+ if (diff.y > E_GESTURE_SWIPE_DIFF_FAIL)
+ {
+ _e_gesture_swipe_cancel();
+ break;
+ }
+ if (diff.x > E_GESTURE_SWIPE_DIFF_SUCCESS)
+ {
+ _e_gesture_send_swipe(idx, swipes->fingers[idx].start.x, swipes->fingers[idx].start.y, swipes->direction, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_LEFT].client, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_LEFT].res);
+ }
+ break;
+ case E_GESTURE_DIRECTION_UP:
+ if (diff.x > E_GESTURE_SWIPE_DIFF_FAIL)
+ {
+ _e_gesture_swipe_cancel();
+ break;
+ }
+ if (diff.y > E_GESTURE_SWIPE_DIFF_SUCCESS)
+ {
+ _e_gesture_send_swipe(idx, swipes->fingers[idx].start.x, swipes->fingers[idx].start.y, swipes->direction, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_UP].client, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_UP].res);
+ }
+ break;
+ case E_GESTURE_DIRECTION_RIGHT:
+ if (diff.y > E_GESTURE_SWIPE_DIFF_FAIL)
+ {
+ _e_gesture_swipe_cancel();
+ break;
+ }
+ if (diff.x > E_GESTURE_SWIPE_DIFF_SUCCESS)
+ {
+ _e_gesture_send_swipe(idx, swipes->fingers[idx].start.x, swipes->fingers[idx].start.y, swipes->direction, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_RIGHT].client, swipes->fingers[idx].direction[E_GESTURE_DIRECTION_RIGHT].res);
+ }
+ break;
+ default:
+ GTWRN("Invalid direction(%d)\n", swipes->direction);
+ break;
+ }
+}
+
+static void
+_e_gesture_process_swipe_up(Ecore_Event_Mouse_Button *ev)
+{
+ _e_gesture_swipe_cancel();
+}
+
+static Eina_Bool
+_e_gesture_process_mouse_button_down(void *event)
+{
+ Ecore_Event_Mouse_Button *ev = event;
+
+ gesture->gesture_events.num_pressed++;
+
+ if (!gesture->grabbed_gesture)
+ {
+ return EINA_TRUE;
+ }
+ if (_e_gesture_is_touch_device(ev->dev_name) == EINA_FALSE)
+ {
+ return EINA_TRUE;
+ }
+ if (ev->multi.device > E_GESTURE_FINGER_MAX)
+ {
+ return EINA_TRUE;
+ }
+
+ if (gesture->gesture_events.num_pressed == 1)
+ {
+ gesture->gesture_events.recognized_gesture = 0x0;
+ }
+
+ if (gesture->gesture_events.recognized_gesture)
+ {
+ return EINA_FALSE;
+ }
+
+ if (gesture->gesture_events.num_pressed == 1)
+ {
+ gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+ }
+
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_SWIPE))
+ {
+ _e_gesture_process_swipe_down(ev);
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_gesture_process_mouse_button_up(void *event)
+{
+ Ecore_Event_Mouse_Button *ev = event;
+
+ gesture->gesture_events.num_pressed--;
+
+ if (!gesture->grabbed_gesture)
+ {
+ return EINA_TRUE;
+ }
+ if (_e_gesture_is_touch_device(ev->dev_name) == EINA_FALSE)
+ {
+ return EINA_TRUE;
+ }
+
+ if (gesture->gesture_events.recognized_gesture)
+ {
+ return EINA_FALSE;
+ }
+
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_SWIPE))
+ {
+ _e_gesture_process_swipe_up(ev);
+ }
+
+ return EINA_TRUE;
+}
+
+
+static Eina_Bool
+_e_gesture_process_mouse_move(void *event)
+{
+ Ecore_Event_Mouse_Move *ev = event;
+
+ if (!gesture->grabbed_gesture)
+ {
+ return EINA_TRUE;
+ }
+ if (_e_gesture_is_touch_device(ev->dev_name) == EINA_FALSE)
+ {
+ return EINA_TRUE;
+ }
+
+ if (gesture->gesture_events.recognized_gesture)
+ {
+ return EINA_FALSE;
+ }
+
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_SWIPE))
+ {
+ _e_gesture_process_swipe_move(ev);
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_gesture_process_key_down(void *event)
+{
+ Ecore_Event_Key *ev = event;
+
+ if (ev->keycode == E_GESTURE_SWIPE_COMBINE_KEY)
+ {
+ gesture->gesture_events.swipes.combined_keycode = E_GESTURE_SWIPE_COMBINE_KEY;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_gesture_process_key_up(void *event)
+{
+ Ecore_Event_Key *ev = event;
+
+ if (ev->keycode == E_GESTURE_SWIPE_COMBINE_KEY)
+ {
+ gesture->gesture_events.swipes.combined_keycode = 0;
+ }
+
+ return EINA_TRUE;
+}
+
+/* Function for checking the existing grab for a key and sending key event(s) */
+Eina_Bool
+e_gesture_process_events(void *event, int type)
+{
+ Eina_Bool res = EINA_TRUE;
+
+ if (type == ECORE_EVENT_MOUSE_BUTTON_DOWN)
+ res = _e_gesture_process_mouse_button_down(event);
+ else if (type == ECORE_EVENT_MOUSE_BUTTON_UP)
+ res = _e_gesture_process_mouse_button_up(event);
+ else if (type == ECORE_EVENT_MOUSE_MOVE)
+ res = _e_gesture_process_mouse_move(event);
+ else if (type == ECORE_EVENT_KEY_DOWN)
+ res = _e_gesture_process_key_down(event);
+ else if (type == ECORE_EVENT_KEY_UP)
+ res = _e_gesture_process_key_up(event);
+ else if (type == ECORE_EVENT_DEVICE_ADD)
+ res = _e_gesture_process_device_add(event);
+ else if (type == ECORE_EVENT_DEVICE_DEL)
+ res = _e_gesture_process_device_del(event);
+
+ return res;
+}
--- /dev/null
+#define E_COMP_WL
+#include "e_mod_main.h"
+#include <string.h>
+
+E_GesturePtr gesture = NULL;
+E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Gesture Module of Window Manager" };
+
+static void *_e_gesture_init(E_Module *m);
+static void _e_gesture_init_handlers(void);
+
+
+static void _e_gesture_wl_client_cb_destroy(struct wl_listener *l, void *data);
+
+static void
+_e_gesture_swipe_set_client_to_list(struct wl_client *client, E_Gesture_Event_Swipe_Finger *fingers, unsigned int direction)
+{
+ if (direction & TIZEN_GESTURE_DIRECTION_DOWN)
+ fingers->direction[E_GESTURE_DIRECTION_DOWN].client = client;
+ if (direction & TIZEN_GESTURE_DIRECTION_LEFT)
+ fingers->direction[E_GESTURE_DIRECTION_LEFT].client = client;
+ if (direction & TIZEN_GESTURE_DIRECTION_UP)
+ fingers->direction[E_GESTURE_DIRECTION_UP].client = client;
+ if (direction & TIZEN_GESTURE_DIRECTION_RIGHT)
+ fingers->direction[E_GESTURE_DIRECTION_RIGHT].client = client;
+}
+
+/* Function for registering wl_client destroy listener */
+int
+e_gesture_add_client_destroy_listener(struct wl_client *client, int mode EINA_UNUSED, int num_of_fingers, unsigned int direction)
+{
+ struct wl_listener *destroy_listener = NULL;
+ Eina_List *l;
+ E_Gesture_Grabbed_Client *grabbed_client, *data;
+
+ EINA_LIST_FOREACH(gesture->grab_client_list, l, data)
+ {
+ if (data->client == client)
+ {
+ _e_gesture_swipe_set_client_to_list(client, &data->swipe_fingers[num_of_fingers], direction);
+
+ return TIZEN_GESTURE_ERROR_NONE;
+ }
+ }
+
+ destroy_listener = E_NEW(struct wl_listener, 1);
+ if (!destroy_listener)
+ {
+ GTERR("Failed to allocate memory for wl_client destroy listener !\n");
+ return TIZEN_GESTURE_ERROR_NO_SYSTEM_RESOURCES;
+ }
+
+ grabbed_client = E_NEW(E_Gesture_Grabbed_Client, 1);
+ if (!grabbed_client)
+ {
+ GTERR("Failed to allocate memory to save client information !\n");
+ return TIZEN_GESTURE_ERROR_NO_SYSTEM_RESOURCES;
+ }
+
+ destroy_listener->notify = _e_gesture_wl_client_cb_destroy;
+ wl_client_add_destroy_listener(client, destroy_listener);
+ grabbed_client->client = client;
+ grabbed_client->destroy_listener = destroy_listener;
+ _e_gesture_swipe_set_client_to_list(client, &grabbed_client->swipe_fingers[num_of_fingers], direction);
+
+ gesture->grab_client_list = eina_list_append(gesture->grab_client_list, grabbed_client);
+
+ return TIZEN_KEYROUTER_ERROR_NONE;
+}
+
+static void
+_e_gesture_remove_client_destroy_listener(struct wl_client *client, unsigned int num_of_fingers, unsigned int direction)
+{
+ Eina_List *l, *l_next;
+ E_Gesture_Grabbed_Client *data;
+ int i;
+
+ EINA_LIST_FOREACH_SAFE(gesture->grab_client_list, l, l_next, data)
+ {
+ if (data->client == client)
+ {
+ _e_gesture_swipe_set_client_to_list(NULL, &data->swipe_fingers[num_of_fingers], direction);
+
+ for (i = 0; i < E_GESTURE_FINGER_MAX+1; i++)
+ {
+ if (data->swipe_fingers[i].direction[E_GESTURE_DIRECTION_DOWN].client ||
+ data->swipe_fingers[i].direction[E_GESTURE_DIRECTION_LEFT].client ||
+ data->swipe_fingers[i].direction[E_GESTURE_DIRECTION_UP].client ||
+ data->swipe_fingers[i].direction[E_GESTURE_DIRECTION_RIGHT].client)
+ {
+ return;
+ }
+ }
+ wl_list_remove(&data->destroy_listener->link);
+ E_FREE(data->destroy_listener);
+ gesture->grab_client_list = eina_list_remove(gesture->grab_client_list, data);
+ E_FREE(data);
+ }
+ }
+}
+
+static void
+_e_gesture_cb_grab_swipe(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t num_of_fingers, uint32_t direction)
+{
+ E_Gesture_Event *gev;
+ unsigned int grabbed_direction = 0x0;
+
+ GTINF("client %p is request grab gesture, fingers: %d, direction: 0x%x\n", client, num_of_fingers, direction);
+ if (num_of_fingers > E_GESTURE_FINGER_MAX)
+ {
+ GTWRN("Do not support %d fingers (max: %d)\n", num_of_fingers, E_GESTURE_FINGER_MAX);
+ tizen_gesture_send_grab_swipe_notify(resource, num_of_fingers, direction, TIZEN_GESTURE_ERROR_INVALID_DATA);
+ goto out;
+ }
+
+ gev = &gesture->gesture_events;
+
+ if (direction & TIZEN_GESTURE_DIRECTION_DOWN)
+ {
+ if (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].client)
+ {
+ grabbed_direction |= TIZEN_GESTURE_DIRECTION_DOWN;
+ }
+ else
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].client = client;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].res = resource;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_LEFT)
+ {
+ if (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].client)
+ {
+ grabbed_direction |= TIZEN_GESTURE_DIRECTION_LEFT;
+ }
+ else
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].client = client;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].res = resource;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_UP)
+ {
+ if (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].client)
+ {
+ grabbed_direction |= TIZEN_GESTURE_DIRECTION_UP;
+ }
+ else
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].client = client;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].res = resource;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_RIGHT)
+ {
+ if (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].client)
+ {
+ grabbed_direction |= TIZEN_GESTURE_DIRECTION_RIGHT;
+ }
+ else
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].client = client;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].res = resource;
+ }
+ }
+
+ if (grabbed_direction)
+ tizen_gesture_send_grab_swipe_notify(resource, num_of_fingers, grabbed_direction, TIZEN_GESTURE_ERROR_GRABBED_ALREADY);
+
+ e_gesture_add_client_destroy_listener(client, TIZEN_GESTURE_TYPE_SWIPE, num_of_fingers, direction & ~grabbed_direction);
+ gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_SWIPE;
+ gev->swipes.fingers[num_of_fingers].enabled = EINA_TRUE;
+
+ if (!grabbed_direction)
+ tizen_gesture_send_grab_swipe_notify(resource, num_of_fingers, direction, TIZEN_GESTURE_ERROR_NONE);
+
+out:
+ return;
+}
+
+static void
+_e_gesture_cb_ungrab_swipe(struct wl_client *client,
+ struct wl_resource *resouce,
+ uint32_t num_of_fingers, uint32_t direction)
+{
+ int i, j;
+ E_Gesture_Event *gev;
+ unsigned int ungrabbed_direction = 0x0;
+ int ret = TIZEN_GESTURE_ERROR_NONE;
+
+ GTINF("client %p is request ungrab swipe gesture, fingers: %d, direction: 0x%x, client: %p\n", client, num_of_fingers, direction, gesture->gesture_events.swipes.fingers[0].direction[3].client);
+
+ if (num_of_fingers > E_GESTURE_FINGER_MAX)
+ {
+ GTWRN("Do not support %d fingers (max: %d)\n", num_of_fingers, E_GESTURE_FINGER_MAX);
+ ret = TIZEN_GESTURE_ERROR_INVALID_DATA;
+ goto finish;
+ }
+
+ gev = &gesture->gesture_events;
+
+ if (direction & TIZEN_GESTURE_DIRECTION_DOWN)
+ {
+ if ((gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].client) &&
+ (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].client == client))
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].client = NULL;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_DOWN].res = NULL;
+ }
+ else
+ {
+ ungrabbed_direction |= TIZEN_GESTURE_DIRECTION_DOWN;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_LEFT)
+ {
+ if ((gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].client) &&
+ (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].client == client))
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].client = NULL;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_LEFT].res = NULL;
+ }
+ else
+ {
+ ungrabbed_direction |= TIZEN_GESTURE_DIRECTION_LEFT;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_UP)
+ {
+ if ((gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].client) &&
+ (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].client == client))
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].client = NULL;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_UP].res = NULL;
+ }
+ else
+ {
+ ungrabbed_direction |= TIZEN_GESTURE_DIRECTION_UP;
+ }
+ }
+ if (direction & TIZEN_GESTURE_DIRECTION_RIGHT)
+ {
+ if ((gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].client) &&
+ (gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].client == client))
+ {
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].client = NULL;
+ gev->swipes.fingers[num_of_fingers].direction[E_GESTURE_DIRECTION_RIGHT].res = NULL;
+ }
+ else
+ {
+ ungrabbed_direction |= TIZEN_GESTURE_DIRECTION_RIGHT;
+ }
+ }
+
+ if (direction & ~ungrabbed_direction)
+ {
+ _e_gesture_remove_client_destroy_listener(client, num_of_fingers, direction & ~ungrabbed_direction);
+ for (i = 0; i < E_GESTURE_FINGER_MAX+1; i++)
+ {
+ for (j = 0; j < E_GESTURE_DIRECTION_MAX+1; j++)
+ {
+ if (gev->swipes.fingers[i].direction[j].client)
+ {
+ goto finish;
+ }
+ }
+ gev->swipes.fingers[i].enabled = EINA_FALSE;
+ }
+ gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_SWIPE;
+ }
+
+finish:
+ tizen_gesture_send_grab_swipe_notify(resouce, num_of_fingers, direction, ret);
+ return;
+}
+
+static const struct tizen_gesture_interface _e_gesture_implementation = {
+ _e_gesture_cb_grab_swipe,
+ _e_gesture_cb_ungrab_swipe
+};
+
+/* tizen_gesture global object destroy function */
+static void
+_e_gesture_cb_destory(struct wl_resource *resource)
+{
+ /* TODO : destroy resources if exist */
+}
+
+/* tizen_keyrouter global object bind function */
+static void
+_e_gesture_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ E_GesturePtr gesture_instance = data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client, &tizen_gesture_interface, MIN(version, 1), id);
+
+ GTDBG("wl_resource_create(...,tizen_gesture_interface,...)\n");
+
+ if (!resource)
+ {
+ GTERR("Failed to create resource ! (version :%d, id:%d)\n", version, id);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &_e_gesture_implementation, gesture_instance, _e_gesture_cb_destory);
+}
+
+
+
+static Eina_Bool
+_e_gesture_event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event)
+{
+ (void) data;
+
+ return e_gesture_process_events(event, type);
+}
+
+static void
+_e_gesture_init_handlers(void)
+{
+ gesture->ef_handler = ecore_event_filter_add(NULL, _e_gesture_event_filter, NULL, NULL);
+}
+
+static void *
+_e_gesture_init(E_Module *m)
+{
+ gesture = E_NEW(E_Gesture, 1);
+
+ if (!gesture)
+ {
+ GTERR("Failed to allocate memory for gesture !\n");
+ return NULL;
+ }
+
+ if (!e_comp)
+ {
+ GTERR("Failed to initialize gesture module ! (e_comp == NULL)\n");
+ goto err;
+ }
+
+ /* Add filtering mechanism */
+ _e_gesture_init_handlers();
+ gesture->global = wl_global_create(e_comp_wl->wl.disp, &tizen_gesture_interface, 1, gesture, _e_gesture_cb_bind);
+ if (!gesture->global)
+ {
+ GTERR("Failed to create global !\n");
+ goto err;
+ }
+
+ gesture->gesture_filter = E_GESTURE_TYPE_MAX;
+
+ return m;
+
+err:
+ if (gesture && gesture->ef_handler) ecore_event_filter_del(gesture->ef_handler);
+ if (gesture) E_FREE(gesture);
+
+ return NULL;
+}
+
+E_API void *
+e_modapi_init(E_Module *m)
+{
+ return _e_gesture_init(m);
+}
+
+E_API int
+e_modapi_shutdown(E_Module *m)
+{
+ return 1;
+}
+
+E_API int
+e_modapi_save(E_Module *m)
+{
+ /* Save something to be kept */
+ return 1;
+}
+
+static void
+_e_gesture_wl_client_cb_destroy(struct wl_listener *l, void *data)
+{
+ struct wl_client *client = data;
+ int i, j;
+ Eina_List *l_list, *l_next;
+ E_Gesture_Grabbed_Client *client_data;
+
+ if (gesture->grabbed_gesture & TIZEN_GESTURE_TYPE_SWIPE)
+ {
+ for (i = 0; i < E_GESTURE_FINGER_MAX+1; i++)
+ {
+ for (j = 0; j < E_GESTURE_DIRECTION_MAX+1; j++)
+ {
+ if (gesture->gesture_events.swipes.fingers[i].direction[j].client == client)
+ {
+ gesture->gesture_events.swipes.fingers[i].direction[j].client = NULL;
+ gesture->gesture_events.swipes.fingers[i].direction[j].res = NULL;
+ }
+ }
+ }
+
+ for (i = 0; i < E_GESTURE_FINGER_MAX+1; i++)
+ {
+ for (j = 0; j < E_GESTURE_DIRECTION_MAX+1; j++)
+ {
+ if (gesture->gesture_events.swipes.fingers[i].direction[j].client)
+ {
+ goto out;
+ }
+ }
+ gesture->gesture_events.swipes.fingers[i].enabled = EINA_FALSE;
+ }
+ gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_SWIPE;
+ }
+
+out:
+ E_FREE(l);
+ l = NULL;
+ EINA_LIST_FOREACH_SAFE(gesture->grab_client_list, l_list, l_next, client_data)
+ {
+ if (client_data->client == client)
+ {
+ gesture->grab_client_list = eina_list_remove(gesture->grab_client_list, client_data);
+ E_FREE(client_data);
+ }
+ }
+}
--- /dev/null
+#ifndef E_MOD_MAIN_H
+#define E_MOD_MAIN_H
+
+#include <tizen-extension-server-protocol.h>
+#include <e.h>
+#include <Ecore_Drm.h>
+
+#define GTERR(msg, ARG...) ERR("[tizen_gesture][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define GTWRN(msg, ARG...) WRN("[tizen_gesture][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define GTINF(msg, ARG...) INF("[tizen_gesture][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+#define GTDBG(msg, ARG...) DBG("[tizen_gesture][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
+
+#define E_GESTURE_FINGER_MAX 3
+#define E_GESTURE_TYPE_MAX TIZEN_GESTURE_TYPE_SWIPE+1
+#define E_GESTURE_TYPE_ALL TIZEN_GESTURE_TYPE_SWIPE
+
+/* FIX ME: Set values in contiguration file, do not use definition */
+#define E_GESTURE_SWIPE_DONE_TIME 0.5
+#define E_GESTURE_SWIPE_START_TIME 0.01
+#define E_GESTURE_SWIPE_START_AREA 50
+#define E_GESTURE_SWIPE_DIFF_FAIL 100
+#define E_GESTURE_SWIPE_DIFF_SUCCESS 300
+#define E_GESTURE_SWIPE_COMBINE_KEY 124
+
+#define ABS(x) ((x)>0)?(x):-(x)
+
+typedef struct _E_Gesture E_Gesture;
+typedef struct _E_Gesture* E_GesturePtr;
+typedef struct _E_Gesture_Event E_Gesture_Event;
+typedef struct _E_Gesture_Event_Swipe E_Gesture_Event_Swipe;
+typedef struct _E_Gesture_Event_Swipe_Finger E_Gesture_Event_Swipe_Finger;
+typedef struct _E_Gesture_Event_Swipe_Finger_Direction E_Gesture_Event_Swipe_Finger_Direction;
+typedef struct _E_Gesture_Grabbed_Client E_Gesture_Grabbed_Client;
+
+typedef struct _Coords Coords;
+
+typedef enum _E_Gesture_Direction E_Gesture_Direction;
+
+extern E_GesturePtr gesture;
+
+#define E_GESTURE_DIRECTION_MAX 4
+enum _E_Gesture_Direction
+{
+ E_GESTURE_DIRECTION_NONE,
+ E_GESTURE_DIRECTION_DOWN, //Start point is North
+ E_GESTURE_DIRECTION_LEFT, // Start point is East
+ E_GESTURE_DIRECTION_UP, // Start point is South
+ E_GESTURE_DIRECTION_RIGHT // Start point is West
+};
+
+struct _Coords
+{
+ int x, y;
+};
+
+struct _E_Gesture_Event_Swipe_Finger_Direction
+{
+ struct wl_client *client;
+ struct wl_resource *res;
+};
+
+struct _E_Gesture_Event_Swipe_Finger
+{
+ Coords start;
+ Eina_Bool enabled;
+ E_Gesture_Event_Swipe_Finger_Direction direction[E_GESTURE_DIRECTION_MAX+1];
+};
+
+struct _E_Gesture_Grabbed_Client
+{
+ struct wl_client *client;
+ struct wl_listener *destroy_listener;
+
+ E_Gesture_Event_Swipe_Finger swipe_fingers[E_GESTURE_FINGER_MAX+1];
+};
+
+
+struct _E_Gesture_Event_Swipe
+{
+ E_Gesture_Event_Swipe_Finger fingers[E_GESTURE_FINGER_MAX+1];
+
+ E_Gesture_Direction direction;
+
+ unsigned int combined_keycode;
+
+ unsigned int enabled_finger;
+ Ecore_Timer *start_timer;
+ Ecore_Timer *done_timer;
+};
+
+struct _E_Gesture_Event
+{
+ E_Gesture_Event_Swipe swipes;
+
+ int num_pressed;
+ Eina_Bool recognized_gesture;
+};
+
+struct _E_Gesture
+{
+ struct wl_global *global;
+
+ Ecore_Event_Filter *ef_handler;
+ Eina_List *handlers;
+ Eina_List *grab_client_list;
+
+ Eina_List *touch_devices;
+
+ unsigned int grabbed_gesture;
+ E_Gesture_Event gesture_events;
+
+ unsigned int gesture_filter;
+ unsigned int gesture_recognized;
+};
+
+/* E Module */
+E_API extern E_Module_Api e_modapi;
+E_API void *e_modapi_init(E_Module *m);
+E_API int e_modapi_shutdown(E_Module *m);
+E_API int e_modapi_save(E_Module *m);
+
+Eina_Bool e_gesture_process_events(void *event, int type);
+int e_gesture_type_convert(uint32_t type);
+#endif