aboutsummaryrefslogtreecommitdiff
path: root/src/input/touch
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/touch')
-rw-r--r--src/input/touch/ITouchActionHandler.h240
-rw-r--r--src/input/touch/ITouchInputHandler.h104
-rw-r--r--src/input/touch/ITouchInputHandling.cpp155
-rw-r--r--src/input/touch/ITouchInputHandling.h87
-rw-r--r--src/input/touch/Makefile6
-rw-r--r--src/input/touch/TouchTypes.h120
-rw-r--r--src/input/touch/generic/GenericTouchActionHandler.cpp196
-rw-r--r--src/input/touch/generic/GenericTouchActionHandler.h83
-rw-r--r--src/input/touch/generic/GenericTouchInputHandler.cpp404
-rw-r--r--src/input/touch/generic/GenericTouchInputHandler.h96
-rw-r--r--src/input/touch/generic/GenericTouchPinchDetector.cpp99
-rw-r--r--src/input/touch/generic/GenericTouchPinchDetector.h42
-rw-r--r--src/input/touch/generic/GenericTouchRotateDetector.cpp129
-rw-r--r--src/input/touch/generic/GenericTouchRotateDetector.h47
-rw-r--r--src/input/touch/generic/GenericTouchSwipeDetector.cpp183
-rw-r--r--src/input/touch/generic/GenericTouchSwipeDetector.h60
-rw-r--r--src/input/touch/generic/IGenericTouchGestureDetector.h103
-rw-r--r--src/input/touch/generic/Makefile10
18 files changed, 2164 insertions, 0 deletions
diff --git a/src/input/touch/ITouchActionHandler.h b/src/input/touch/ITouchActionHandler.h
new file mode 100644
index 0000000000..4a3b5b8321
--- /dev/null
+++ b/src/input/touch/ITouchActionHandler.h
@@ -0,0 +1,240 @@
+#pragma once
+/*
+ * Copyright (C) 2012-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdint.h>
+
+/*!
+ * \ingroup touch
+ * \brief Directions in which a touch can moved
+ *
+ * These values can be combined (bitwise OR) to specify multiple directions.
+ */
+typedef enum {
+ TouchMoveDirectionNone = 0x0,
+ TouchMoveDirectionLeft = 0x1,
+ TouchMoveDirectionRight = 0x2,
+ TouchMoveDirectionUp = 0x4,
+ TouchMoveDirectionDown = 0x8
+} TouchMoveDirection;
+
+/*!
+ * \ingroup touch
+ * \brief Interface defining all supported touch action events
+ */
+class ITouchActionHandler
+{
+public:
+ virtual ~ITouchActionHandler() { }
+
+ /*!
+ * \brief A touch action has been aborted
+ */
+ virtual void OnTouchAbort() { };
+
+ /*!
+ * \brief A single touch has started
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ *
+ * \return True if the event was handled otherwise false
+ *
+ * \sa OnSingleTap
+ */
+ virtual bool OnSingleTouchStart(float x, float y) { return true; }
+ /*!
+ * \brief A single touch has been held down for a certain amount of time
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ *
+ * \return True if the event was handled otherwise false
+ *
+ * \sa OnSingleLongPress
+ */
+ virtual bool OnSingleTouchHold(float x, float y) { return true; }
+ /*!
+ * \brief A single touch has moved
+ *
+ * \param x The x coordinate (with sub-pixel) of the current touch
+ * \param y The y coordinate (with sub-pixel) of the current touch
+ * \param offsetX The covered distance on the x axis (with sub-pixel)
+ * \param offsetX The covered distance on the y axis (with sub-pixel)
+ * \param velocityX The velocity of the gesture in x direction (pixels/second)
+ * \param velocityX The velocity of the gesture in y direction (pixels/second)
+ *
+ * \return True if the event was handled otherwise false
+ *
+ * \sa OnTouchGesturePan
+ */
+ virtual bool OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; }
+ /*!
+ * \brief A single touch has been lifted
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ *
+ * \return True if the event was handled otherwise false
+ *
+ * \sa OnSingleTap
+ */
+ virtual bool OnSingleTouchEnd(float x, float y) { return true; }
+
+ /*!
+ * \brief An additional touch has been performed
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param pointer The pointer that has performed the touch
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnMultiTouchDown(float x, float y, int32_t pointer) { return true; }
+ /*!
+ * \brief Multiple simultaneous touches have been held down for a certain amount of time
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param pointers The number of pointers involved (default 2)
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnMultiTouchHold(float x, float y, int32_t pointers = 2) { return true; }
+ /*!
+ * \brief A touch has moved
+ *
+ * \param x The x coordinate (with sub-pixel) of the current touch
+ * \param y The y coordinate (with sub-pixel) of the current touch
+ * \param offsetX The covered distance on the x axis (with sub-pixel)
+ * \param offsetX The covered distance on the y axis (with sub-pixel)
+ * \param velocityX The velocity of the gesture in x direction (pixels/second)
+ * \param velocityX The velocity of the gesture in y direction (pixels/second)
+ * \param pointer The pointer that has performed the touch
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer) { return true; }
+ /*!
+ * \brief A touch has been lifted (but there are still active touches)
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param pointer The pointer that has performed the touch
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnMultiTouchUp(float x, float y, int32_t pointer) { return true; }
+
+ /*!
+ * \brief A pan gesture with a single touch has been started
+ *
+ * \param x The x coordinate (with sub-pixel) of the initial touch
+ * \param y The y coordinate (with sub-pixel) of the initial touch
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchGestureStart(float x, float y) { return true; }
+ /*!
+ * \brief A pan gesture with a single touch is in progress
+ *
+ * \param x The x coordinate (with sub-pixel) of the current touch
+ * \param y The y coordinate (with sub-pixel) of the current touch
+ * \param offsetX The covered distance on the x axis (with sub-pixel)
+ * \param offsetX The covered distance on the y axis (with sub-pixel)
+ * \param velocityX The velocity of the gesture in x direction (pixels/second)
+ * \param velocityX The velocity of the gesture in y direction (pixels/second)
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; }
+ /*!
+ * \brief A pan gesture with a single touch has ended
+ *
+ * \param x The x coordinate (with sub-pixel) of the current touch
+ * \param y The y coordinate (with sub-pixel) of the current touch
+ * \param offsetX The covered distance on the x axis (with sub-pixel)
+ * \param offsetX The covered distance on the y axis (with sub-pixel)
+ * \param velocityX The velocity of the gesture in x direction (pixels/second)
+ * \param velocityX The velocity of the gesture in y direction (pixels/second)
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchGestureEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; }
+
+ // convenience events
+ /*!
+ * \brief A tap with a one or more touches has been performed
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param pointers The number of pointers involved (default 1)
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual void OnTap(float x, float y, int32_t pointers = 1) { }
+ /*!
+ * \brief One or more touches have been held down for a certain amount of time
+ *
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param pointers The number of pointers involved (default 1)
+ *
+ * \return True if the event was handled otherwise false
+ *
+ * \sa OnSingleTouchHold
+ */
+ virtual void OnLongPress(float x, float y, int32_t pointers = 1) { }
+ /*!
+ * \brief One or more touches has been moved quickly in a single direction in a short time
+ *
+ * \param direction The direction (left, right, up, down) of the swipe gesture
+ * \param xDown The x coordinate (with sub-pixel) of the first touch
+ * \param yDown The y coordinate (with sub-pixel) of the first touch
+ * \param xUp The x coordinate (with sub-pixel) of the last touch
+ * \param yUp The y coordinate (with sub-pixel) of the last touch
+ * \param velocityX The velocity of the gesture in x direction (pixels/second)
+ * \param velocityX The velocity of the gesture in y direction (pixels/second)
+ * \param pointers The number of pointers involved (default 1)
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual void OnSwipe(TouchMoveDirection direction, float xDown, float yDown, float xUp, float yUp, float velocityX, float velocityY, int32_t pointers = 1) { }
+ /*!
+ * \brief Two simultaneous touches have been held down and moved to perform a zooming/pinching gesture
+ *
+ * \param centerX The x coordinate (with sub-pixel) of the center of the two touches
+ * \param centerY The y coordinate (with sub-pixel) of the center of the two touches
+ * \param zoomFactor The zoom (> 1.0) or pinch (< 1.0) factor of the two touches
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor) { }
+ /*!
+ * \brief Two simultaneous touches have been held down and moved to perform a rotating gesture
+ *
+ * \param centerX The x coordinate (with sub-pixel) of the center of the two touches
+ * \param centerY The y coordinate (with sub-pixel) of the center of the two touches
+ * \param angle The clockwise angle in degrees of the rotation
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual void OnRotate(float centerX, float centerY, float angle) { }
+}; \ No newline at end of file
diff --git a/src/input/touch/ITouchInputHandler.h b/src/input/touch/ITouchInputHandler.h
new file mode 100644
index 0000000000..6ea47dbc8d
--- /dev/null
+++ b/src/input/touch/ITouchInputHandler.h
@@ -0,0 +1,104 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdint.h>
+
+#include "input/touch/ITouchInputHandling.h"
+
+/*!
+ * \ingroup touch
+ * \brief Touch input event
+ */
+typedef enum {
+ TouchInputAbort,
+ TouchInputDown,
+ TouchInputUp,
+ TouchInputMove
+} TouchInput;
+
+/*!
+ * \ingroup touch
+ * \brief Interface (implements ITouchInputHandling) defining methods to handle
+ * raw touch input events (down, up, move).
+ *
+ * This interface should be implemented on platforms only supporting low level
+ * (raw) touch input events like touch down/up/move and with no gesture
+ * recognition logic.
+ */
+class ITouchInputHandler : public ITouchInputHandling
+{
+public:
+ ITouchInputHandler()
+ : m_dpi(160.0f)
+ { }
+ virtual ~ITouchInputHandler() { }
+
+ /*!
+ * \brief Handle a touch event
+ *
+ * Handles the given touch event at the given location.
+ * This takes into account all the currently active pointers
+ * which need to be updated before calling this method to
+ * actually interprete and handle the changes in touch.
+ *
+ * \param event The actual touch event (abort, down, up, move)
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param time The time (in nanoseconds) when this touch occured
+ * \param pointer The number of the touch pointer which caused this event (default 0)
+ * \param size The size of the touch pointer (with sub-pixel) (default 0.0)
+ *
+ * \return True if the event was handled otherwise false.
+ *
+ * \sa Update
+ */
+ virtual bool HandleTouchInput(TouchInput event, float x, float y, int64_t time, int32_t pointer = 0, float size = 0.0f) = 0;
+
+ /*!
+ * \brief Update the coordinates of a pointer
+ *
+ * Depending on how a platform handles touch input and provides the necessary events
+ * this method needs to be called at different times. If there's an event for every
+ * touch action this method does not need to be called at all. If there's only a
+ * touch event for the primary pointer (and no special events for any secondary
+ * pointers in a multi touch gesture) this method should be called for every active
+ * secondary pointer before calling Handle.
+ *
+ * \param pointer The number of the touch pointer which caused this event (default 0)
+ * \param x The x coordinate (with sub-pixel) of the touch
+ * \param y The y coordinate (with sub-pixel) of the touch
+ * \param time The time (in nanoseconds) when this touch occured
+ * \param size The size of the touch pointer (with sub-pixel) (default 0.0)
+ *
+ * \return True if the pointer was updated otherwise false.
+ *
+ * \sa Handle
+ */
+ virtual bool UpdateTouchPointer(int32_t pointer, float x, float y, int64_t time, float size = 0.0f) { return false; }
+
+ void SetScreenDPI(float dpi) { if (dpi > 0.0f) m_dpi = dpi; }
+
+protected:
+ /*!
+ * \brief DPI value of the touch screen
+ */
+ float m_dpi;
+};
diff --git a/src/input/touch/ITouchInputHandling.cpp b/src/input/touch/ITouchInputHandling.cpp
new file mode 100644
index 0000000000..458e66c21d
--- /dev/null
+++ b/src/input/touch/ITouchInputHandling.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ITouchInputHandling.h"
+
+void ITouchInputHandling::RegisterHandler(ITouchActionHandler *touchHandler)
+{
+ m_handler = touchHandler;
+}
+
+void ITouchInputHandling::UnregisterHandler()
+{
+ m_handler = NULL;
+}
+
+void ITouchInputHandling::OnTouchAbort()
+{
+ if (m_handler)
+ m_handler->OnTouchAbort();
+}
+
+bool ITouchInputHandling::OnSingleTouchStart(float x, float y)
+{
+ if (m_handler)
+ return m_handler->OnSingleTouchStart(x, y);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnSingleTouchHold(float x, float y)
+{
+ if (m_handler)
+ return m_handler->OnSingleTouchHold(x, y);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ if (m_handler)
+ return m_handler->OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnSingleTouchEnd(float x, float y)
+{
+ if (m_handler)
+ return m_handler->OnSingleTouchEnd(x, y);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnMultiTouchDown(float x, float y, int32_t pointer)
+{
+ if (m_handler)
+ return m_handler->OnMultiTouchDown(x, y, pointer);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnMultiTouchHold(float x, float y, int32_t pointers /* = 2 */)
+{
+ if (m_handler)
+ return m_handler->OnMultiTouchHold(x, y, pointers);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer)
+{
+ if (m_handler)
+ return m_handler->OnMultiTouchMove(x, y, offsetX, offsetY, velocityX, velocityY, pointer);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnMultiTouchUp(float x, float y, int32_t pointer)
+{
+ if (m_handler)
+ return m_handler->OnMultiTouchUp(x, y, pointer);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnTouchGestureStart(float x, float y)
+{
+ if (m_handler)
+ return m_handler->OnTouchGestureStart(x, y);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ if (m_handler)
+ return m_handler->OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+bool ITouchInputHandling::OnTouchGestureEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ if (m_handler)
+ return m_handler->OnTouchGestureEnd(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+void ITouchInputHandling::OnTap(float x, float y, int32_t pointers /* = 1 */)
+{
+ if (m_handler)
+ m_handler->OnTap(x, y, pointers);
+}
+
+void ITouchInputHandling::OnLongPress(float x, float y, int32_t pointers /* = 1 */)
+{
+ if (m_handler)
+ m_handler->OnLongPress(x, y, pointers);
+}
+
+void ITouchInputHandling::OnSwipe(TouchMoveDirection direction, float xDown, float yDown, float xUp, float yUp, float velocityX, float velocityY, int32_t pointers /* = 1 */)
+{
+ if (m_handler)
+ m_handler->OnSwipe(direction, xDown, yDown, xUp, yUp, velocityX, velocityY, pointers);
+}
+
+void ITouchInputHandling::OnZoomPinch(float centerX, float centerY, float zoomFactor)
+{
+ if (m_handler)
+ m_handler->OnZoomPinch(centerX, centerY, zoomFactor);
+}
+
+void ITouchInputHandling::OnRotate(float centerX, float centerY, float angle)
+{
+ if (m_handler)
+ m_handler->OnRotate(centerX, centerY, angle);
+}
diff --git a/src/input/touch/ITouchInputHandling.h b/src/input/touch/ITouchInputHandling.h
new file mode 100644
index 0000000000..f88cf9038b
--- /dev/null
+++ b/src/input/touch/ITouchInputHandling.h
@@ -0,0 +1,87 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "input/touch/ITouchActionHandler.h"
+
+/*!
+ * \ingroup touch
+ * \brief Convencience interface implementing ITouchActionHandler with an
+ * implementation that forwards any ITouchActionHandler-related calls
+ * to a previously registered ITouchActionHandler
+ *
+ * \sa ITouchActionHandler
+ */
+class ITouchInputHandling : protected ITouchActionHandler
+{
+public:
+ ITouchInputHandling()
+ : m_handler(NULL)
+ { }
+ virtual ~ITouchInputHandling() { }
+
+ /*!
+ * \brief Register a touch input handler
+ *
+ * There can only be one touch input handler.
+ *
+ * \param touchHandler An instance of a touch handler implementing the
+ * ITouchActionHandler interface
+ *
+ * \sa UnregisterHandler
+ */
+ void RegisterHandler(ITouchActionHandler *touchHandler);
+ /*!
+ * \brief Unregister the previously registered touch handler
+ *
+ * \sa RegisterHandler
+ */
+ void UnregisterHandler();
+
+protected:
+ // implementation of ITouchActionHandler
+ virtual void OnTouchAbort();
+
+ virtual bool OnSingleTouchStart(float x, float y);
+ virtual bool OnSingleTouchHold(float x, float y);
+ virtual bool OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+ virtual bool OnSingleTouchEnd(float x, float y);
+
+ virtual bool OnMultiTouchDown(float x, float y, int32_t pointer);
+ virtual bool OnMultiTouchHold(float x, float y, int32_t pointers = 2);
+ virtual bool OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer);
+ virtual bool OnMultiTouchUp(float x, float y, int32_t pointer);
+
+ virtual bool OnTouchGestureStart(float x, float y);
+ virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+ virtual bool OnTouchGestureEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+
+ // convenience events
+ virtual void OnTap(float x, float y, int32_t pointers = 1);
+ virtual void OnLongPress(float x, float y, int32_t pointers = 1);
+ virtual void OnSwipe(TouchMoveDirection direction, float xDown, float yDown, float xUp, float yUp, float velocityX, float velocityY, int32_t pointers = 1);
+ virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor);
+ virtual void OnRotate(float centerX, float centerY, float angle);
+
+private:
+ ITouchActionHandler *m_handler;
+};
diff --git a/src/input/touch/Makefile b/src/input/touch/Makefile
new file mode 100644
index 0000000000..6672614b60
--- /dev/null
+++ b/src/input/touch/Makefile
@@ -0,0 +1,6 @@
+SRCS=ITouchInputHandling.cpp \
+
+LIB=input_touch.a
+
+include ../../../Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
diff --git a/src/input/touch/TouchTypes.h b/src/input/touch/TouchTypes.h
new file mode 100644
index 0000000000..b4cc1e3ddb
--- /dev/null
+++ b/src/input/touch/TouchTypes.h
@@ -0,0 +1,120 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "utils/Vector.h"
+
+/*!
+ * \ingroup touch
+ * \brief A class representing a touch consisting of an x and y coordinate and
+ * a time
+ */
+class Touch : public CVector
+{
+public:
+ Touch() { reset(); }
+ virtual ~Touch() { }
+
+ /*!
+ * \brief Resets the x/y coordinates and the time
+ */
+ virtual void reset() { CVector::reset(); time = -1; }
+
+ /*!
+ * \brief Checks if the touch is valid i.e. if the x/y coordinates and the
+ * time are >= 0
+ *
+ * \return True if the touch is valid otherwise false
+ */
+ bool valid() const { return x >= 0.0f && y >= 0.0f && time >= 0; }
+
+ /*!
+ * \brief Copies the x/y coordinates and the time from the given touch
+ *
+ * \param other Touch to copy x/y coordinates and time from
+ */
+ void copy(const Touch &other) { x = other.x; y = other.y; time = other.time; }
+
+ int64_t time; // in nanoseconds
+};
+
+/*!
+ * \ingroup touch
+ * \brief A class representing a touch pointer interaction consisting of an
+ * down touch, the last touch and the current touch.
+ */
+class Pointer
+{
+public:
+ Pointer() { reset(); }
+
+ /*!
+ * \brief Resets the pointer and all its touches
+ */
+ void reset() { down.reset(); last.reset(); moving = false; size = 0.0f; }
+
+ /*!
+ * \brief Checks if the "down" touch is valid
+ *
+ * \return True if the "down" touch is valid otherwise false
+ */
+ bool valid() const { return down.valid(); }
+
+ /*!
+ * \brief Calculates the velocity in x/y direction using the "down" and
+ * either the "last" or "current" touch
+ *
+ * \param velocityX Placeholder for velocity in x direction
+ * \param velocityY Placeholder for velocity in y direction
+ * \param fromLast Whether to calculate the velocity with the "last" or
+ * the "current" touch
+ *
+ * \return True if the velocity is valid otherwise false
+ */
+ bool velocity(float &velocityX, float &velocityY, bool fromLast = true) const
+ {
+ int64_t fromTime = last.time;
+ float fromX = last.x;
+ float fromY = last.y;
+ if (!fromLast)
+ {
+ fromTime = down.time;
+ fromX = down.x;
+ fromY = down.y;
+ }
+
+ velocityX = 0.0f; // number of pixels per second
+ velocityY = 0.0f; // number of pixels per second
+
+ int64_t timeDiff = current.time - fromTime;
+ if (timeDiff <= 0)
+ return false;
+
+ velocityX = ((current.x - fromX) * 1000000000) / timeDiff;
+ velocityY = ((current.y - fromY) * 1000000000) / timeDiff;
+ return true;
+ }
+
+ Touch down;
+ Touch last;
+ Touch current;
+ bool moving;
+ float size;
+}; \ No newline at end of file
diff --git a/src/input/touch/generic/GenericTouchActionHandler.cpp b/src/input/touch/generic/GenericTouchActionHandler.cpp
new file mode 100644
index 0000000000..db57c987a0
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchActionHandler.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GenericTouchActionHandler.h"
+#include "ApplicationMessenger.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/Key.h"
+#include "windowing/WinEvents.h"
+
+CGenericTouchActionHandler &CGenericTouchActionHandler::Get()
+{
+ static CGenericTouchActionHandler sTouchAction;
+ return sTouchAction;
+}
+
+void CGenericTouchActionHandler::OnTouchAbort()
+{ }
+
+bool CGenericTouchActionHandler::OnSingleTouchStart(float x, float y)
+{
+ focusControl(x, y);
+
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnSingleTouchHold(float x, float y)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnSingleTouchEnd(float x, float y)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnMultiTouchDown(float x, float y, int32_t pointer)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnMultiTouchHold(float x, float y, int32_t pointers /* = 2 */)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnMultiTouchUp(float x, float y, int32_t pointer)
+{
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnTouchGestureStart(float x, float y)
+{
+ sendEvent(ACTION_GESTURE_BEGIN, x, y, 0.0f, 0.0f);
+
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ sendEvent(ACTION_GESTURE_PAN, x, y, offsetX, offsetY);
+
+ return true;
+}
+
+bool CGenericTouchActionHandler::OnTouchGestureEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ sendEvent(ACTION_GESTURE_END, velocityX, velocityY, x, y);
+
+ return true;
+}
+
+void CGenericTouchActionHandler::OnTap(float x, float y, int32_t pointers /* = 1 */)
+{
+ if (pointers <= 0 || pointers > 10)
+ return;
+
+ sendEvent(ACTION_TOUCH_TAP, (uint16_t)x, (uint16_t)y, 0.0f, 0.0f, pointers);
+}
+
+void CGenericTouchActionHandler::OnLongPress(float x, float y, int32_t pointers /* = 1 */)
+{
+ if (pointers <= 0 || pointers > 10)
+ return;
+
+ sendEvent(ACTION_TOUCH_LONGPRESS, (uint16_t)x, (uint16_t)y, 0.0f, 0.0f, pointers);
+}
+
+void CGenericTouchActionHandler::OnSwipe(TouchMoveDirection direction, float xDown, float yDown, float xUp, float yUp, float velocityX, float velocityY, int32_t pointers /* = 1 */)
+{
+ if (pointers <= 0 || pointers > 10)
+ return;
+
+ int actionId = 0;
+ if (direction == TouchMoveDirectionLeft)
+ actionId = ACTION_GESTURE_SWIPE_LEFT;
+ else if (direction == TouchMoveDirectionRight)
+ actionId = ACTION_GESTURE_SWIPE_RIGHT;
+ else if (direction == TouchMoveDirectionUp)
+ actionId = ACTION_GESTURE_SWIPE_UP;
+ else if (direction == TouchMoveDirectionDown)
+ actionId = ACTION_GESTURE_SWIPE_DOWN;
+ else
+ return;
+
+ sendEvent(actionId, xUp, yUp, velocityX, velocityY, pointers);
+}
+
+void CGenericTouchActionHandler::OnZoomPinch(float centerX, float centerY, float zoomFactor)
+{
+ sendEvent(ACTION_GESTURE_ZOOM, centerX, centerY, zoomFactor, 0.0f);
+}
+
+void CGenericTouchActionHandler::OnRotate(float centerX, float centerY, float angle)
+{
+ sendEvent(ACTION_GESTURE_ROTATE, centerX, centerY, angle, 0.0f);
+}
+
+int CGenericTouchActionHandler::QuerySupportedGestures(float x, float y)
+{
+ CGUIMessage msg(GUI_MSG_GESTURE_NOTIFY, 0, 0, (int)x, (int)y);
+ if (!g_windowManager.SendMessage(msg))
+ return 0;
+
+ return msg.GetParam1();
+}
+
+void CGenericTouchActionHandler::touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y)
+{
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+
+ newEvent.type = type;
+ newEvent.button.type = type;
+ newEvent.button.button = button;
+ newEvent.button.x = x;
+ newEvent.button.y = y;
+
+ CWinEvents::MessagePush(&newEvent);
+}
+
+void CGenericTouchActionHandler::sendEvent(int actionId, float x, float y, float x2 /* = 0.0f */, float y2 /* = 0.0f */, int pointers /* = 1 */)
+{
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+
+ newEvent.type = XBMC_TOUCH;
+ newEvent.touch.type = XBMC_TOUCH;
+ newEvent.touch.action = actionId;
+ newEvent.touch.x = x;
+ newEvent.touch.y = y;
+ newEvent.touch.x2 = x2;
+ newEvent.touch.y2 = y2;
+ newEvent.touch.pointers = pointers;
+
+ CWinEvents::MessagePush(&newEvent);
+}
+
+void CGenericTouchActionHandler::focusControl(float x, float y)
+{
+ XBMC_Event newEvent;
+ memset(&newEvent, 0, sizeof(newEvent));
+
+ newEvent.type = XBMC_SETFOCUS;
+ newEvent.focus.type = XBMC_SETFOCUS;
+ newEvent.focus.x = (uint16_t)x;
+ newEvent.focus.y = (uint16_t)y;
+
+ CWinEvents::MessagePush(&newEvent);
+}
diff --git a/src/input/touch/generic/GenericTouchActionHandler.h b/src/input/touch/generic/GenericTouchActionHandler.h
new file mode 100644
index 0000000000..b4917b89f2
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchActionHandler.h
@@ -0,0 +1,83 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "input/touch/ITouchActionHandler.h"
+
+/*!
+ * \ingroup touch_generic
+ * \brief Generic implementation of ITouchActionHandler to translate
+ * touch actions into XBMC specific and mappable actions.
+ *
+ * \sa ITouchActionHandler
+ */
+class CGenericTouchActionHandler : public ITouchActionHandler
+{
+public:
+ /*!
+ \brief Get an instance of the touch input manager
+ */
+ static CGenericTouchActionHandler &Get();
+
+ // implementation of ITouchActionHandler
+ virtual void OnTouchAbort();
+
+ virtual bool OnSingleTouchStart(float x, float y);
+ virtual bool OnSingleTouchHold(float x, float y);
+ virtual bool OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+ virtual bool OnSingleTouchEnd(float x, float y);
+
+ virtual bool OnMultiTouchDown(float x, float y, int32_t pointer);
+ virtual bool OnMultiTouchHold(float x, float y, int32_t pointers = 2);
+ virtual bool OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer);
+ virtual bool OnMultiTouchUp(float x, float y, int32_t pointer);
+
+ virtual bool OnTouchGestureStart(float x, float y);
+ virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+ virtual bool OnTouchGestureEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+
+ // convenience events
+ virtual void OnTap(float x, float y, int32_t pointers = 1);
+ virtual void OnLongPress(float x, float y, int32_t pointers = 1);
+ virtual void OnSwipe(TouchMoveDirection direction, float xDown, float yDown, float xUp, float yUp, float velocityX, float velocityY, int32_t pointers = 1);
+ virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor);
+ virtual void OnRotate(float centerX, float centerY, float angle);
+
+ /*!
+ \brief Asks the control at the given coordinates for a list of the supported gestures.
+
+ \param x The x coordinate (with sub-pixel) of the touch
+ \param y The y coordinate (with sub-pixel) of the touch
+
+ \return EVENT_RESULT value of bitwise ORed gestures.
+ */
+ int QuerySupportedGestures(float x, float y);
+
+private:
+ // private construction, and no assignements; use the provided singleton methods
+ CGenericTouchActionHandler() { }
+ CGenericTouchActionHandler(const CGenericTouchActionHandler&);
+ CGenericTouchActionHandler const& operator=(CGenericTouchActionHandler const&);
+ virtual ~CGenericTouchActionHandler() { }
+
+ void touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y);
+ void sendEvent(int actionId, float x, float y, float x2 = 0.0f, float y2 = 0.0f, int pointers = 1);
+ void focusControl(float x, float y);
+};
diff --git a/src/input/touch/generic/GenericTouchInputHandler.cpp b/src/input/touch/generic/GenericTouchInputHandler.cpp
new file mode 100644
index 0000000000..4c91563998
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchInputHandler.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2012-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <math.h>
+
+#include "GenericTouchInputHandler.h"
+#include "input/touch/generic/GenericTouchPinchDetector.h"
+#include "input/touch/generic/GenericTouchRotateDetector.h"
+#include "input/touch/generic/GenericTouchSwipeDetector.h"
+#include "threads/SingleLock.h"
+#include "utils/log.h"
+
+#define TOUCH_HOLD_TIMEOUT 1000
+CGenericTouchInputHandler::CGenericTouchInputHandler()
+ : m_gestureState(TouchGestureUnknown),
+ m_gestureStateOld(TouchGestureUnknown)
+{
+ m_holdTimer = new CTimer(this);
+}
+
+CGenericTouchInputHandler::~CGenericTouchInputHandler()
+{
+ delete m_holdTimer;
+
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ delete (*detector);
+ m_detectors.clear();
+}
+
+CGenericTouchInputHandler &CGenericTouchInputHandler::Get()
+{
+ static CGenericTouchInputHandler sTouchInput;
+ return sTouchInput;
+}
+
+bool CGenericTouchInputHandler::HandleTouchInput(TouchInput event, float x, float y, int64_t time, int32_t pointer /* = 0 */, float size /* = 0.0f */)
+{
+ if (time < 0 || pointer < 0 || pointer >= TOUCH_MAX_POINTERS)
+ return false;
+
+ CSingleLock lock(m_critical);
+
+ bool result = true;
+
+ m_pointers[pointer].current.x = x;
+ m_pointers[pointer].current.y = y;
+ m_pointers[pointer].current.time = time;
+
+ switch (event)
+ {
+ case TouchInputAbort:
+ {
+ triggerDetectors(event, pointer);
+
+ setGestureState(TouchGestureUnknown);
+ for (unsigned int pIndex = 0; pIndex < TOUCH_MAX_POINTERS; pIndex++)
+ m_pointers[pIndex].reset();
+
+ OnTouchAbort();
+ break;
+ }
+
+ case TouchInputDown:
+ {
+ m_pointers[pointer].down.x = x;
+ m_pointers[pointer].down.y = y;
+ m_pointers[pointer].down.time = time;
+ m_pointers[pointer].moving = false;
+ m_pointers[pointer].size = size;
+
+ // If this is the down event of the primary pointer
+ // we start by assuming that it's a single touch
+ if (pointer == 0)
+ {
+ // create new gesture detectors
+ m_detectors.insert(new CGenericTouchSwipeDetector(this, m_dpi));
+ m_detectors.insert(new CGenericTouchPinchDetector(this, m_dpi));
+ m_detectors.insert(new CGenericTouchRotateDetector(this, m_dpi));
+ triggerDetectors(event, pointer);
+
+ setGestureState(TouchGestureSingleTouch);
+ result = OnSingleTouchStart(x, y);
+
+ m_holdTimer->Start(TOUCH_HOLD_TIMEOUT);
+ }
+ // Otherwise it's the down event of another pointer
+ else
+ {
+ triggerDetectors(event, pointer);
+
+ // If we so far assumed single touch or still have the primary
+ // pointer of a previous multi touch pressed down, we can update to multi touch
+ if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold ||
+ m_gestureState == TouchGestureMultiTouchDone)
+ {
+ result = OnMultiTouchDown(x, y, pointer);
+ m_holdTimer->Stop(true);
+
+ if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold)
+ m_holdTimer->Start(TOUCH_HOLD_TIMEOUT);
+
+ setGestureState(TouchGestureMultiTouchStart);
+ }
+ // Otherwise we should ignore this pointer
+ else
+ {
+ m_pointers[pointer].reset();
+ break;
+ }
+ }
+ return result;
+ }
+
+ case TouchInputUp:
+ {
+ // unexpected event => abort
+ if (!m_pointers[pointer].valid() ||
+ m_gestureState == TouchGestureUnknown)
+ break;
+
+ triggerDetectors(event, pointer);
+
+ m_holdTimer->Stop(false);
+
+ // Just a single tap with a pointer
+ if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold)
+ {
+ result = OnSingleTouchEnd(x, y);
+
+ if (m_gestureState == TouchGestureSingleTouch)
+ OnTap(x, y, 1);
+ }
+ // A pan gesture started with a single pointer (ignoring any other pointers)
+ else if (m_gestureState == TouchGesturePan)
+ {
+ float velocityX = 0.0f; // number of pixels per second
+ float velocityY = 0.0f; // number of pixels per second
+ m_pointers[pointer].velocity(velocityX, velocityY, false);
+
+ result = OnTouchGestureEnd(x, y,
+ x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y,
+ velocityX, velocityY);
+ }
+ // we are in multi-touch
+ else
+ result = OnMultiTouchUp(x, y, pointer);
+
+ // If we were in multi touch mode and lifted one pointer
+ // we can go into the TouchGestureMultiTouchDone state which will allow
+ // the user to go back into multi touch mode without lifting the primary pointer
+ if (m_gestureState == TouchGestureMultiTouchStart || m_gestureState == TouchGestureMultiTouchHold || m_gestureState == TouchGestureMultiTouch)
+ {
+ setGestureState(TouchGestureMultiTouchDone);
+
+ // after lifting the primary pointer, the secondary pointer will
+ // become the primary pointer in the next event
+ if (pointer == 0)
+ {
+ m_pointers[0] = m_pointers[1];
+ pointer = 1;
+ }
+ }
+ // Otherwise abort
+ else
+ {
+ if (m_gestureState == TouchGestureMultiTouchDone)
+ {
+ float velocityX = 0.0f; // number of pixels per second
+ float velocityY = 0.0f; // number of pixels per second
+ m_pointers[pointer].velocity(velocityX, velocityY, false);
+
+ result = OnTouchGestureEnd(x, y,
+ x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y,
+ velocityX, velocityY);
+
+ // if neither of the two pointers moved we have a single tap with multiple pointers
+ if (m_gestureStateOld != TouchGestureMultiTouchHold && m_gestureStateOld != TouchGestureMultiTouch)
+ OnTap(fabs((m_pointers[0].down.x + m_pointers[1].down.x) / 2),
+ fabs((m_pointers[0].down.y + m_pointers[1].down.y) / 2),
+ 2);
+ }
+
+ setGestureState(TouchGestureUnknown);
+ m_pointers[pointer].reset();
+ }
+
+ return result;
+ }
+
+ case TouchInputMove:
+ {
+ // unexpected event => abort
+ if (!m_pointers[pointer].valid() ||
+ m_gestureState == TouchGestureUnknown ||
+ m_gestureState == TouchGestureMultiTouchDone)
+ break;
+
+ bool moving = false;
+ for (unsigned int index = 0; index < TOUCH_MAX_POINTERS; index++)
+ {
+ if (m_pointers[index].valid() && m_pointers[index].moving)
+ {
+ moving = true;
+ break;
+ }
+ }
+
+ if (moving)
+ {
+ m_holdTimer->Stop();
+
+ // the touch is moving so we start a gesture
+ if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureMultiTouchStart)
+ result = OnTouchGestureStart(m_pointers[pointer].down.x, m_pointers[pointer].down.y);
+ }
+
+ triggerDetectors(event, pointer);
+
+ if (m_gestureState == TouchGestureSingleTouch)
+ {
+ // Check if the touch has moved far enough to count as movement
+ if (!m_pointers[pointer].moving)
+ break;
+
+ m_pointers[pointer].last.copy(m_pointers[pointer].down);
+ setGestureState(TouchGesturePan);
+ }
+ else if (m_gestureState == TouchGestureMultiTouchStart)
+ {
+ setGestureState(TouchGestureMultiTouch);
+
+ // set the starting point
+ saveLastTouch();
+ }
+
+ float offsetX = x - m_pointers[pointer].last.x;
+ float offsetY = y - m_pointers[pointer].last.y;
+ float velocityX = 0.0f; // number of pixels per second
+ float velocityY = 0.0f; // number of pixels per second
+ m_pointers[pointer].velocity(velocityX, velocityY);
+
+ if (m_pointers[pointer].moving &&
+ (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || m_gestureState == TouchGesturePan))
+ result = OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ // Let's see if we have a pan gesture (i.e. the primary and only pointer moving)
+ if (m_gestureState == TouchGesturePan)
+ {
+ result = OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ m_pointers[pointer].last.x = x;
+ m_pointers[pointer].last.y = y;
+ }
+ else if (m_gestureState == TouchGestureMultiTouch)
+ {
+ if (moving)
+ result = OnMultiTouchMove(x, y,offsetX, offsetY, velocityX, velocityY, pointer);
+ }
+ else
+ break;
+
+ return result;
+ }
+
+ default:
+ CLog::Log(LOGDEBUG, "CGenericTouchInputHandler: unknown TouchInput");
+ break;
+ }
+
+ return false;
+}
+
+bool CGenericTouchInputHandler::UpdateTouchPointer(int32_t pointer, float x, float y, int64_t time, float size /* = 0.0f */)
+{
+ if (pointer < 0 || pointer >= TOUCH_MAX_POINTERS)
+ return false;
+
+ CSingleLock lock(m_critical);
+
+ m_pointers[pointer].last.copy(m_pointers[pointer].current);
+
+ m_pointers[pointer].current.x = x;
+ m_pointers[pointer].current.y = y;
+ m_pointers[pointer].current.time = time;
+ if (size > 0.0f)
+ m_pointers[pointer].size = size;
+
+ // calculate whether the pointer has moved at all
+ if (!m_pointers[pointer].moving)
+ {
+ CVector down = m_pointers[pointer].down;
+ CVector current = m_pointers[pointer].current;
+ CVector distance = down - current;
+
+ if (distance.length() > m_pointers[pointer].size)
+ m_pointers[pointer].moving = true;
+ }
+
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ (*detector)->OnTouchUpdate(pointer, m_pointers[pointer]);
+
+ return true;
+}
+
+void CGenericTouchInputHandler::saveLastTouch()
+{
+ for (unsigned int pointer = 0; pointer < TOUCH_MAX_POINTERS; pointer++)
+ m_pointers[pointer].last.copy(m_pointers[pointer].current);
+}
+
+void CGenericTouchInputHandler::OnTimeout()
+{
+ CSingleLock lock(m_critical);
+
+ switch (m_gestureState)
+ {
+ case TouchGestureSingleTouch:
+ setGestureState(TouchGestureSingleTouchHold);
+
+ OnSingleTouchHold(m_pointers[0].down.x, m_pointers[0].down.y);
+ OnLongPress(m_pointers[0].down.x, m_pointers[0].down.y, 1);
+ break;
+
+ case TouchGestureMultiTouchStart:
+ if (!m_pointers[0].moving && !m_pointers[1].moving)
+ {
+ setGestureState(TouchGestureMultiTouchHold);
+
+ OnMultiTouchHold(m_pointers[0].down.x, m_pointers[0].down.y);
+ OnLongPress(fabs((m_pointers[0].down.x + m_pointers[1].down.x) / 2),
+ fabs((m_pointers[0].down.y + m_pointers[1].down.y) / 2),
+ 2);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void CGenericTouchInputHandler::triggerDetectors(TouchInput event, int32_t pointer)
+{
+ switch (event)
+ {
+ case TouchInputAbort:
+ {
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ delete (*detector);
+ m_detectors.clear();
+ break;
+ }
+
+ case TouchInputDown:
+ {
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ (*detector)->OnTouchDown(pointer, m_pointers[pointer]);
+ break;
+ }
+
+ case TouchInputUp:
+ {
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ (*detector)->OnTouchUp(pointer, m_pointers[pointer]);
+ break;
+ }
+
+ case TouchInputMove:
+ {
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ (*detector)->OnTouchMove(pointer, m_pointers[pointer]);
+ break;
+ }
+
+ default:
+ return;
+ }
+
+ std::set<IGenericTouchGestureDetector*> finishedDetectors;
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = m_detectors.begin(); detector != m_detectors.end(); detector++)
+ {
+ if ((*detector)->IsDone())
+ finishedDetectors.insert(*detector);
+ }
+
+ for (std::set<IGenericTouchGestureDetector*>::const_iterator detector = finishedDetectors.begin(); detector != finishedDetectors.end(); detector++)
+ m_detectors.erase(*detector);
+}
diff --git a/src/input/touch/generic/GenericTouchInputHandler.h b/src/input/touch/generic/GenericTouchInputHandler.h
new file mode 100644
index 0000000000..df0cc679aa
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchInputHandler.h
@@ -0,0 +1,96 @@
+#pragma once
+/*
+ * Copyright (C) 2012-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <set>
+
+#include "input/touch/ITouchInputHandler.h"
+#include "input/touch/TouchTypes.h"
+#include "threads/CriticalSection.h"
+#include "threads/Timer.h"
+
+#define TOUCH_MAX_POINTERS 2
+
+class IGenericTouchGestureDetector;
+
+/*!
+ * \ingroup touch_generic
+ * \brief Generic implementation of ITouchInputHandler to handle low level (raw)
+ * touch events and translate them into touch actions which are passed
+ * on to the registered ITouchActionHandler implementation.
+ *
+ * The generic implementation supports single a double touch and hold
+ * actions and basic gesture recognition for panning, swiping, pinching/zooming
+ * and rotating.
+ *
+ * \sa ITouchInputHandler
+ */
+class CGenericTouchInputHandler : public ITouchInputHandler, private ITimerCallback
+{
+public:
+ /*!
+ \brief Get an instance of the touch input manager
+ */
+ static CGenericTouchInputHandler &Get();
+
+ // implementation of ITouchInputHandler
+ virtual bool HandleTouchInput(TouchInput event, float x, float y, int64_t time, int32_t pointer = 0, float size = 0.0f);
+ virtual bool UpdateTouchPointer(int32_t pointer, float x, float y, int64_t time, float size = 0.0f);
+
+private:
+ // private construction, and no assignements; use the provided singleton methods
+ CGenericTouchInputHandler();
+ CGenericTouchInputHandler(const CGenericTouchInputHandler&);
+ CGenericTouchInputHandler const& operator=(CGenericTouchInputHandler const&);
+ virtual ~CGenericTouchInputHandler();
+
+ typedef enum {
+ TouchGestureUnknown = 0,
+ // only primary pointer active but stationary so far
+ TouchGestureSingleTouch,
+ // primary pointer active but stationary for a certain time
+ TouchGestureSingleTouchHold,
+ // primary pointer moving
+ TouchGesturePan,
+ // at least two pointers active but stationary so far
+ TouchGestureMultiTouchStart,
+ // at least two pointers active but stationary for a certain time
+ TouchGestureMultiTouchHold,
+ // at least two pointers active and moving
+ TouchGestureMultiTouch,
+ // all but primary pointer have been lifted
+ TouchGestureMultiTouchDone
+ } TouchGestureState;
+
+ // implementation of ITimerCallback
+ virtual void OnTimeout();
+
+ void saveLastTouch();
+ void setGestureState(TouchGestureState gestureState) { m_gestureStateOld = m_gestureState; m_gestureState = gestureState; }
+ void triggerDetectors(TouchInput event, int32_t pointer);
+
+ CCriticalSection m_critical;
+ CTimer *m_holdTimer;
+ Pointer m_pointers[TOUCH_MAX_POINTERS];
+ std::set<IGenericTouchGestureDetector*> m_detectors;
+
+ TouchGestureState m_gestureState;
+ TouchGestureState m_gestureStateOld;
+};
diff --git a/src/input/touch/generic/GenericTouchPinchDetector.cpp b/src/input/touch/generic/GenericTouchPinchDetector.cpp
new file mode 100644
index 0000000000..8c3d004b38
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchPinchDetector.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GenericTouchPinchDetector.h"
+
+bool CGenericTouchPinchDetector::OnTouchDown(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ m_pointers[index] = pointer;
+ return true;
+}
+
+bool CGenericTouchPinchDetector::OnTouchUp(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ // after lifting the primary pointer, the secondary pointer will
+ // become the primary pointer in the next event
+ if (index == 0)
+ {
+ m_pointers[0] = m_pointers[1];
+ index = 1;
+ }
+
+ m_pointers[index].reset();
+
+ if (!m_pointers[0].valid() && !m_pointers[1].valid())
+ m_done = true;
+
+ return true;
+}
+
+bool CGenericTouchPinchDetector::OnTouchMove(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ // update the internal pointers
+ m_pointers[index] = pointer;
+
+ Pointer& primaryPointer = m_pointers[0];
+ Pointer& secondaryPointer = m_pointers[1];
+
+ if (!primaryPointer.valid() || !secondaryPointer.valid() ||
+ (!primaryPointer.moving && !secondaryPointer.moving))
+ return false;
+
+ // calculate zoom/pinch
+ CVector primary = primaryPointer.down;
+ CVector secondary = secondaryPointer.down;
+ CVector diagonal = primary - secondary;
+
+ float baseDiffLength = diagonal.length();
+ if (baseDiffLength != 0.0f)
+ {
+ CVector primaryNow = primaryPointer.current;
+ CVector secondaryNow = secondaryPointer.current;
+ CVector diagonalNow = primaryNow - secondaryNow;
+ float curDiffLength = diagonalNow.length();
+
+ float centerX = (primary.x + secondary.x) / 2;
+ float centerY = (primary.y + secondary.y) / 2;
+
+ float zoom = curDiffLength / baseDiffLength;
+
+ OnZoomPinch(centerX, centerY, zoom);
+ }
+
+ return true;
+}
diff --git a/src/input/touch/generic/GenericTouchPinchDetector.h b/src/input/touch/generic/GenericTouchPinchDetector.h
new file mode 100644
index 0000000000..6bddf8386b
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchPinchDetector.h
@@ -0,0 +1,42 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "input/touch/generic/IGenericTouchGestureDetector.h"
+
+/*!
+ * \ingroup touch_generic
+ * \brief Implementation of IGenericTouchGestureDetector to detect pinch/zoom
+ * gestures with at least two active touch pointers.
+ *
+ * \sa IGenericTouchGestureDetector
+ */
+class CGenericTouchPinchDetector : public IGenericTouchGestureDetector
+{
+public:
+ CGenericTouchPinchDetector(ITouchActionHandler *handler, float dpi)
+ : IGenericTouchGestureDetector(handler, dpi)
+ { }
+ virtual ~CGenericTouchPinchDetector() { }
+
+ virtual bool OnTouchDown(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchUp(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchMove(unsigned int index, const Pointer &pointer);
+};
diff --git a/src/input/touch/generic/GenericTouchRotateDetector.cpp b/src/input/touch/generic/GenericTouchRotateDetector.cpp
new file mode 100644
index 0000000000..6462e06c0d
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchRotateDetector.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <math.h>
+
+#include "GenericTouchRotateDetector.h"
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795028842
+#endif
+
+CGenericTouchRotateDetector::CGenericTouchRotateDetector(ITouchActionHandler *handler, float dpi)
+ : IGenericTouchGestureDetector(handler, dpi),
+ m_angle(0.0f)
+{ }
+
+bool CGenericTouchRotateDetector::OnTouchDown(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ m_pointers[index] = pointer;
+ m_angle = 0.0f;
+ return true;
+}
+
+bool CGenericTouchRotateDetector::OnTouchUp(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ // after lifting the primary pointer, the secondary pointer will
+ // become the primary pointer in the next event
+ if (index == 0)
+ {
+ m_pointers[0] = m_pointers[1];
+ index = 1;
+ }
+
+ m_pointers[index].reset();
+
+ if (!m_pointers[0].valid() && !m_pointers[1].valid())
+ m_done = true;
+
+ return true;
+}
+
+bool CGenericTouchRotateDetector::OnTouchMove(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ // update the internal pointers
+ m_pointers[index] = pointer;
+
+ Pointer& primaryPointer = m_pointers[0];
+ Pointer& secondaryPointer = m_pointers[1];
+
+ if (!primaryPointer.valid() || !secondaryPointer.valid() ||
+ (!primaryPointer.moving && !secondaryPointer.moving))
+ return false;
+
+ CVector last = primaryPointer.last - secondaryPointer.last;
+ CVector current = primaryPointer.current - secondaryPointer.current;
+
+ float length = last.length() * current.length();
+ if (length != 0.0f)
+ {
+ float centerX = (primaryPointer.current.x + secondaryPointer.current.x) / 2;
+ float centerY = (primaryPointer.current.y + secondaryPointer.current.y) / 2;
+ float scalar = last.scalar(current);
+ float angle = acos(scalar / length) * 180.0f / M_PI;
+
+ // make sure the result of acos is a valid number
+ if (angle == angle)
+ {
+ // calculate the direction of the rotation using the
+ // z-component of the cross-product of last and current
+ float direction = last.x * current.y - current.x * last.y;
+ if (direction < 0.0f)
+ m_angle -= angle;
+ else
+ m_angle += angle;
+
+ OnRotate(centerX, centerY, m_angle);
+ }
+ }
+
+ return true;
+}
+
+bool CGenericTouchRotateDetector::OnTouchUpdate(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ // update the internal pointers
+ m_pointers[index] = pointer;
+ return true;
+}
diff --git a/src/input/touch/generic/GenericTouchRotateDetector.h b/src/input/touch/generic/GenericTouchRotateDetector.h
new file mode 100644
index 0000000000..31e15565a5
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchRotateDetector.h
@@ -0,0 +1,47 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "input/touch/generic/IGenericTouchGestureDetector.h"
+
+/*!
+ * \ingroup touch_generic
+ * \brief Implementation of IGenericTouchGestureDetector to detect rotation
+ * gestures with at least two active touch pointers.
+ *
+ * \sa IGenericTouchGestureDetector
+ */
+class CGenericTouchRotateDetector : public IGenericTouchGestureDetector
+{
+public:
+ CGenericTouchRotateDetector(ITouchActionHandler *handler, float dpi);
+ virtual ~CGenericTouchRotateDetector() { }
+
+ virtual bool OnTouchDown(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchUp(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchMove(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchUpdate(unsigned int index, const Pointer &pointer);
+
+private:
+ /*!
+ * \brief Angle of the detected rotation
+ */
+ float m_angle;
+};
diff --git a/src/input/touch/generic/GenericTouchSwipeDetector.cpp b/src/input/touch/generic/GenericTouchSwipeDetector.cpp
new file mode 100644
index 0000000000..2b792724c3
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchSwipeDetector.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _USE_MATH_DEFINES
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+#include <stdlib.h>
+
+#include "GenericTouchSwipeDetector.h"
+
+// maximum time between touch down and up (in nanoseconds)
+#define SWIPE_MAX_TIME 500000000
+// maxmium swipe distance between touch down and up (in multiples of screen DPI)
+#define SWIPE_MIN_DISTANCE 0.5f
+// original maximum variance of the touch movement
+#define SWIPE_MAX_VARIANCE 0.2f
+// tangens of the maximum angle (20 degrees) the touch movement may vary in a
+// direction perpendicular to the swipe direction (in radians)
+// => tan(20 deg) = tan(20 * M_PI / 180)
+#define SWIPE_MAX_VARIANCE_ANGLE 0.36397023f
+
+CGenericTouchSwipeDetector::CGenericTouchSwipeDetector(ITouchActionHandler *handler, float dpi)
+ : IGenericTouchGestureDetector(handler, dpi),
+ m_directions(TouchMoveDirectionLeft | TouchMoveDirectionRight | TouchMoveDirectionUp | TouchMoveDirectionDown),
+ m_swipeDetected(false), m_size(0)
+{ }
+
+bool CGenericTouchSwipeDetector::OnTouchDown(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ m_size += 1;
+ if (m_size > 1)
+ return true;
+
+ // reset all values
+ m_done = false;
+ m_swipeDetected = false;
+ m_directions = TouchMoveDirectionLeft | TouchMoveDirectionRight | TouchMoveDirectionUp | TouchMoveDirectionDown;
+
+ return true;
+}
+
+bool CGenericTouchSwipeDetector::OnTouchUp(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ m_size -= 1;
+ if (m_done)
+ return false;
+
+ m_done = true;
+
+ // check if a swipe has been detected and if it has a valid direction
+ if (!m_swipeDetected || m_directions == TouchMoveDirectionNone)
+ return false;
+
+ // check if the swipe has been performed in the proper time span
+ if ((pointer.current.time - pointer.down.time) > SWIPE_MAX_TIME)
+ return false;
+
+ // calculate the velocity of the swipe
+ float velocityX = 0.0f; // number of pixels per second
+ float velocityY = 0.0f; // number of pixels per second
+ pointer.velocity(velocityX, velocityY, false);
+
+ // call the OnSwipe() callback
+ OnSwipe((TouchMoveDirection)m_directions, pointer.down.x, pointer.down.y, pointer.current.x, pointer.current.y, velocityX, velocityY, m_size + 1);
+ return true;
+}
+
+bool CGenericTouchSwipeDetector::OnTouchMove(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ // only handle swipes of moved pointers
+ if (index >= m_size || m_done || !pointer.moving)
+ return false;
+
+ float deltaXmovement = pointer.current.x - pointer.last.x;
+ float deltaYmovement = pointer.current.y - pointer.last.y;
+
+ if (deltaXmovement > 0.0f)
+ m_directions &= ~TouchMoveDirectionLeft;
+ else if (deltaXmovement < 0.0f)
+ m_directions &= ~TouchMoveDirectionRight;
+
+ if (deltaYmovement > 0.0f)
+ m_directions &= ~TouchMoveDirectionUp;
+ else if (deltaYmovement < 0.0f)
+ m_directions &= ~TouchMoveDirectionDown;
+
+ if (m_directions == TouchMoveDirectionNone)
+ {
+ m_done = true;
+ return false;
+ }
+
+ float deltaXabs = abs(pointer.current.x - pointer.down.x);
+ float deltaYabs = abs(pointer.current.y - pointer.down.y);
+ float varXabs = deltaYabs * SWIPE_MAX_VARIANCE_ANGLE + (m_dpi * SWIPE_MAX_VARIANCE) / 2;
+ float varYabs = deltaXabs * SWIPE_MAX_VARIANCE_ANGLE + (m_dpi * SWIPE_MAX_VARIANCE) / 2;
+
+ if (m_directions & TouchMoveDirectionLeft)
+ {
+ // check if the movement went too much in Y direction
+ if (deltaYabs > varYabs)
+ m_directions &= ~TouchMoveDirectionLeft;
+ // check if the movement went far enough in the X direction
+ else if (deltaXabs > m_dpi * SWIPE_MIN_DISTANCE)
+ m_swipeDetected = true;
+ }
+
+ if (m_directions & TouchMoveDirectionRight)
+ {
+ // check if the movement went too much in Y direction
+ if (deltaYabs > varYabs)
+ m_directions &= ~TouchMoveDirectionRight;
+ // check if the movement went far enough in the X direction
+ else if (deltaXabs > m_dpi * SWIPE_MIN_DISTANCE)
+ m_swipeDetected = true;
+ }
+
+ if (m_directions & TouchMoveDirectionUp)
+ {
+ // check if the movement went too much in X direction
+ if (deltaXabs > varXabs)
+ m_directions &= ~TouchMoveDirectionUp;
+ // check if the movement went far enough in the Y direction
+ else if (deltaYabs > m_dpi * SWIPE_MIN_DISTANCE)
+ m_swipeDetected = true;
+ }
+
+ if (m_directions & TouchMoveDirectionDown)
+ {
+ // check if the movement went too much in X direction
+ if (deltaXabs > varXabs)
+ m_directions &= ~TouchMoveDirectionDown;
+ // check if the movement went far enough in the Y direction
+ else if (deltaYabs > m_dpi * SWIPE_MIN_DISTANCE)
+ m_swipeDetected = true;
+ }
+
+ if (m_directions == TouchMoveDirectionNone)
+ {
+ m_done = true;
+ return false;
+ }
+
+ return true;
+}
+
+bool CGenericTouchSwipeDetector::OnTouchUpdate(unsigned int index, const Pointer &pointer)
+{
+ if (index < 0 || index >= TOUCH_MAX_POINTERS)
+ return false;
+
+ if (m_done)
+ return true;
+
+ return OnTouchMove(index, pointer);
+}
diff --git a/src/input/touch/generic/GenericTouchSwipeDetector.h b/src/input/touch/generic/GenericTouchSwipeDetector.h
new file mode 100644
index 0000000000..528b6d6a07
--- /dev/null
+++ b/src/input/touch/generic/GenericTouchSwipeDetector.h
@@ -0,0 +1,60 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "input/touch/generic/IGenericTouchGestureDetector.h"
+
+/*!
+ * \ingroup touch_generic
+ * \brief Implementation of IGenericTouchGestureDetector to detect swipe
+ * gestures in any direction.
+ *
+ * \sa IGenericTouchGestureDetector
+ */
+class CGenericTouchSwipeDetector : public IGenericTouchGestureDetector
+{
+public:
+ CGenericTouchSwipeDetector(ITouchActionHandler *handler, float dpi);
+ virtual ~CGenericTouchSwipeDetector() { }
+
+ virtual bool OnTouchDown(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchUp(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchMove(unsigned int index, const Pointer &pointer);
+ virtual bool OnTouchUpdate(unsigned int index, const Pointer &pointer);
+
+private:
+ /*!
+ * \brief Swipe directions that are still possible to detect
+ *
+ * The directions are stored as a combination (bitwise OR) of
+ * TouchMoveDirection enum values
+ *
+ * \sa TouchMoveDirection
+ */
+ unsigned int m_directions;
+ /*!
+ * \brief Whether a swipe gesture has been detected or not
+ */
+ bool m_swipeDetected;
+ /*!
+ * \brief Number of active pointeres
+ */
+ unsigned int m_size;
+};
diff --git a/src/input/touch/generic/IGenericTouchGestureDetector.h b/src/input/touch/generic/IGenericTouchGestureDetector.h
new file mode 100644
index 0000000000..c52dbc0403
--- /dev/null
+++ b/src/input/touch/generic/IGenericTouchGestureDetector.h
@@ -0,0 +1,103 @@
+#pragma once
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "input/touch/ITouchInputHandling.h"
+#include "input/touch/TouchTypes.h"
+
+#define TOUCH_MAX_POINTERS 2
+
+/*!
+ * \ingroup touch_generic
+ * \brief Interface defining methods to perform gesture recognition
+ */
+class IGenericTouchGestureDetector : public ITouchInputHandling
+{
+public:
+ IGenericTouchGestureDetector(ITouchActionHandler *handler, float dpi)
+ : m_done(false),
+ m_dpi(dpi)
+ {
+ RegisterHandler(handler);
+ }
+ virtual ~IGenericTouchGestureDetector() { }
+
+ /*!
+ * \brief Check whether the gesture recognition is finished or not
+ *
+ * \return True if the gesture recognition is finished otherwise false
+ */
+ bool IsDone() { return m_done; }
+
+ /*!
+ * \brief A new touch pointer has been recognised.
+ *
+ * \param index Index of the given touch pointer
+ * \param pointer Touch pointer that has changed
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchDown(unsigned int index, const Pointer &pointer) = 0;
+ /*!
+ * \brief An active touch pointer has vanished.
+ *
+ * If the first touch pointer is lifted and there are more active touch
+ * pointers, the remaining pointers change their index.
+ *
+ * \param index Index of the given touch pointer
+ * \param pointer Touch pointer that has changed
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchUp(unsigned int index, const Pointer &pointer) { return false; }
+ /*!
+ * \brief An active touch pointer has moved.
+ *
+ * \param index Index of the given touch pointer
+ * \param pointer Touch pointer that has changed
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchMove(unsigned int index, const Pointer &pointer) { return false; }
+ /*!
+ * \brief An active touch pointer's values have been updated but no event has
+ * occured.
+ *
+ * \param index Index of the given touch pointer
+ * \param pointer Touch pointer that has changed
+ *
+ * \return True if the event was handled otherwise false
+ */
+ virtual bool OnTouchUpdate(unsigned int index, const Pointer &pointer) { return false; }
+
+protected:
+ /*!
+ * \brief Whether the gesture recognition is finished or not
+ */
+ bool m_done;
+ /*!
+ * \brief DPI value of the touch screen
+ */
+ float m_dpi;
+ /*!
+ * \brief Local list of all known touch pointers
+ */
+ Pointer m_pointers[TOUCH_MAX_POINTERS];
+};
diff --git a/src/input/touch/generic/Makefile b/src/input/touch/generic/Makefile
new file mode 100644
index 0000000000..5c3d89fc11
--- /dev/null
+++ b/src/input/touch/generic/Makefile
@@ -0,0 +1,10 @@
+SRCS=GenericTouchActionHandler.cpp \
+ GenericTouchInputHandler.cpp \
+ GenericTouchPinchDetector.cpp \
+ GenericTouchRotateDetector.cpp \
+ GenericTouchSwipeDetector.cpp \
+
+LIB=input_touch_generic.a
+
+include ../../../../Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))