Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[droid] add generic CTouchInput handling logic

  • Loading branch information...
commit 94b7d217103ea3d0abeb12bd0d1ac9f40f47ea02 1 parent b8e8394
@Montellese Montellese authored Cory Fields committed
View
1  xbmc/input/Makefile
@@ -4,6 +4,7 @@ SRCS=ButtonTranslator.cpp \
KeyboardStat.cpp \
MouseStat.cpp \
SDLJoystick.cpp \
+ TouchInput.cpp \
XBMC_keytable.cpp \
LIB=input.a
View
549 xbmc/input/TouchInput.cpp
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2012 Team XBMC
+ * http://www.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 "TouchInput.h"
+#include "threads/SingleLock.h"
+#include "utils/log.h"
+
+CTouchInput::CTouchInput()
+ : m_holdTimeout(1000),
+ m_handler(NULL),
+ m_gestureState(TouchGestureUnknown),
+ m_gestureStateOld(TouchGestureUnknown)
+{
+ m_holdTimer = new CTimer(this);
+}
+
+CTouchInput::~CTouchInput()
+{
+ delete m_holdTimer;
+}
+
+CTouchInput &CTouchInput::Get()
+{
+ static CTouchInput sTouchInput;
+ return sTouchInput;
+}
+
+void CTouchInput::RegisterHandler(ITouchHandler *touchHandler)
+{
+ m_handler = touchHandler;
+}
+
+void CTouchInput::UnregisterHandler()
+{
+ m_handler = NULL;
+}
+
+void CTouchInput::SetTouchHoldTimeout(int32_t timeout)
+{
+ if (timeout <= 0)
+ return;
+
+ m_holdTimeout = timeout;
+}
+
+bool CTouchInput::Handle(TouchEvent 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 TouchEventAbort:
+ {
+ CLog::Log(LOGDEBUG, "CTouchInput: TouchEventAbort");
+ setGestureState(TouchGestureUnknown);
+ for (unsigned int pIndex = 0; pIndex < TOUCH_MAX_POINTERS; pIndex++)
+ m_pointers[pIndex].reset();
+
+ OnTouchAbort();
+ break;
+ }
+
+ case TouchEventDown:
+ {
+ CLog::Log(LOGDEBUG, "CTouchInput: TouchEventDown");
+ 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)
+ {
+ setGestureState(TouchGestureSingleTouch);
+ result = OnSingleTouchStart(x, y);
+
+ m_holdTimer->Start(m_holdTimeout);
+ }
+ // Otherwise it's the down event of another pointer
+ else
+ {
+ // 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)
+ {
+ if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold)
+ {
+ result = OnMultiTouchStart(x, y);
+
+ m_holdTimer->Stop(true);
+ m_holdTimer->Start(m_holdTimeout);
+ }
+ else
+ {
+ result = OnMultiTouchDown(x, y, pointer);
+
+ m_holdTimer->Stop(false);
+ }
+
+ setGestureState(TouchGestureMultiTouchStart);
+ }
+ // Otherwise we should ignore this pointer
+ else
+ {
+ m_pointers[pointer].reset();
+ break;
+ }
+ }
+ return result;
+ }
+
+ case TouchEventUp:
+ {
+ CLog::Log(LOGDEBUG, "CTouchInput: TouchEventUp");
+ // unexpected event => abort
+ if (!m_pointers[pointer].valid() ||
+ m_gestureState == TouchGestureUnknown)
+ break;
+
+ 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)
+ OnSingleTap(x, y);
+ }
+ // 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 = OnTouchGesturePanEnd(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)
+ {
+ result = OnMultiTouchEnd(m_pointers[0].down.x, m_pointers[0].down.y);
+
+ // if neither of the two pointers moved we have a double tap
+ if (m_gestureStateOld != TouchGestureMultiTouchHold && m_gestureStateOld != TouchGestureMultiTouch)
+ OnDoubleTap(m_pointers[0].down.x, m_pointers[0].down.y,
+ m_pointers[1].down.x, m_pointers[1].down.y);
+ }
+
+ setGestureState(TouchGestureUnknown);
+ }
+
+ m_pointers[pointer].reset();
+ return result;
+ }
+
+ case TouchEventMove:
+ {
+ CLog::Log(LOGDEBUG, "CTouchInput: TouchEventMove");
+ // unexpected event => abort
+ if (!m_pointers[pointer].valid() ||
+ m_gestureState == TouchGestureUnknown ||
+ m_gestureState == TouchGestureMultiTouchDone)
+ break;
+
+ m_holdTimer->Stop();
+
+ if (m_gestureState == TouchGestureSingleTouch)
+ {
+ // Check if the touch has moved far enough to count as movement
+ if (!m_pointers[pointer].moving)
+ break;
+
+ result = OnTouchGesturePanStart(m_pointers[pointer].down.x, m_pointers[pointer].down.y);
+
+ 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 (m_pointers[pointer].moving)
+ result = OnMultiTouchMove(x, y,offsetX, offsetY, velocityX, velocityY, pointer);
+
+ handleMultiTouchGesture();
+ }
+ else
+ break;
+
+ return result;
+ }
+
+ default:
+ CLog::Log(LOGDEBUG, "CTouchInput: unknown TouchEvent");
+ break;
+ }
+
+ return false;
+}
+
+bool CTouchInput::Update(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;
+ }
+
+ return true;
+}
+
+void CTouchInput::saveLastTouch()
+{
+ for (unsigned int pointer = 0; pointer < TOUCH_MAX_POINTERS; pointer++)
+ m_pointers[pointer].last.copy(m_pointers[pointer].current);
+}
+
+void CTouchInput::handleMultiTouchGesture()
+{
+ handleZoomPinch();
+}
+
+void CTouchInput::handleZoomPinch()
+{
+ Pointer& primaryPointer = m_pointers[0];
+ Pointer& secondaryPointer = m_pointers[1];
+
+ // 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);
+ }
+}
+
+void CTouchInput::OnTimeout()
+{
+ CSingleLock lock(m_critical);
+
+ switch (m_gestureState)
+ {
+ case TouchGestureSingleTouch:
+ setGestureState(TouchGestureSingleTouchHold);
+
+ OnSingleTouchHold(m_pointers[0].down.x, m_pointers[0].down.y);
+ OnSingleLongPress(m_pointers[0].down.x, m_pointers[0].down.y);
+ 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);
+ OnDoubleLongPress(m_pointers[0].down.x, m_pointers[0].down.y, m_pointers[1].down.x, m_pointers[1].down.y);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void CTouchInput::OnTouchAbort()
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnTouchAbort();
+}
+
+bool CTouchInput::OnSingleTouchStart(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnSingleTouchStart(x, y);
+
+ return true;
+}
+
+bool CTouchInput::OnSingleTouchHold(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnSingleTouchHold(x, y);
+
+ return true;
+}
+
+bool CTouchInput::OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+bool CTouchInput::OnSingleTouchEnd(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnSingleTouchEnd(x, y);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchStart(float x, float y, int32_t pointers /* = 2 */)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchStart(x, y, pointers);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchDown(float x, float y, int32_t pointer)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchDown(x, y, pointer);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchHold(float x, float y, int32_t pointers /* = 2 */)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchHold(x, y, pointers);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchMove(x, y, offsetX, offsetY, velocityX, velocityY, pointer);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchUp(float x, float y, int32_t pointer)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchUp(x, y, pointer);
+
+ return true;
+}
+
+bool CTouchInput::OnMultiTouchEnd(float x, float y, int32_t pointers /* = 2 */)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnMultiTouchEnd(x, y, pointers);
+
+ return true;
+}
+
+bool CTouchInput::OnTouchGesturePanStart(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnTouchGesturePanStart(x, y);
+
+ return true;
+}
+
+bool CTouchInput::OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+bool CTouchInput::OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ return m_handler->OnTouchGesturePanEnd(x, y, offsetX, offsetY, velocityX, velocityY);
+
+ return true;
+}
+
+void CTouchInput::OnSingleTap(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnSingleTap(x, y);
+}
+
+void CTouchInput::OnSingleLongPress(float x, float y)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnSingleLongPress(x, y);
+}
+
+void CTouchInput::OnDoubleTap(float x1, float y1, float x2, float y2)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnDoubleTap(x1, y1, x2, y2);
+}
+
+void CTouchInput::OnDoubleLongPress(float x1, float y1, float x2, float y2)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnDoubleLongPress(x1, y1, x2, y2);
+}
+
+void CTouchInput::OnZoomPinch(float centerX, float centerY, float zoomFactor)
+{
+ CLog::Log(LOGDEBUG, "%s", __FUNCTION__);
+
+ if (m_handler)
+ m_handler->OnZoomPinch(centerX, centerY, zoomFactor);
+}
View
414 xbmc/input/TouchInput.h
@@ -0,0 +1,414 @@
+#pragma once
+/*
+ * Copyright (C) 2012 Team XBMC
+ * http://www.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 "threads/CriticalSection.h"
+#include "threads/Timer.h"
+#include "utils/Vector.h"
+
+#define TOUCH_MAX_POINTERS 2
+
+class ITouchHandler
+{
+public:
+ virtual ~ITouchHandler() { }
+
+ /*!
+ \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 A multi touch gesture has started
+
+ \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 OnMultiTouchStart(float x, float y, int32_t pointers = 2) { 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
+ \sa OnDoubleLongPress
+ */
+ 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 multi touch gesture has ended (the last 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
+ \param pointers The number of pointers involved (default 2)
+ \return True if the event was handled otherwise false
+ */
+ virtual bool OnMultiTouchEnd(float x, float y, int32_t pointers = 2) { 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 OnTouchGesturePanStart(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 OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; }
+
+ // convenience events
+ /*!
+ \brief A tap with a single 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
+ \return True if the event was handled otherwise false
+ */
+ virtual void OnSingleTap(float x, float y) { }
+ /*!
+ \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 OnSingleTouchHold
+ */
+ virtual void OnSingleLongPress(float x, float y) { }
+ /*!
+ \brief A tap with two simultaneous touches has been performed
+
+ \param x1 The x coordinate (with sub-pixel) of the first touch
+ \param y1 The y coordinate (with sub-pixel) of the first touch
+ \param x2 The x coordinate (with sub-pixel) of the second touch
+ \param y2 The y coordinate (with sub-pixel) of the second touch
+ \return True if the event was handled otherwise false
+ \sa
+ */
+ virtual void OnDoubleTap(float x1, float y1, float x2, float y2) { }
+ /*!
+ \brief Two simultaneous touches have been held down for a certain amount of time
+
+ \param x1 The x coordinate (with sub-pixel) of the first touch
+ \param y1 The y coordinate (with sub-pixel) of the first touch
+ \param x2 The x coordinate (with sub-pixel) of the second touch
+ \param y2 The y coordinate (with sub-pixel) of the second touch
+ \return True if the event was handled otherwise false
+ \sa OnMultiTouchHold
+ */
+ virtual void OnDoubleLongPress(float x1, float y1, float x2, float y2) { }
+ /*!
+ \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
+ \sa
+ */
+ virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor) { }
+};
+
+class CTouchInput : private ITouchHandler, private ITimerCallback
+{
+public:
+ typedef enum {
+ TouchEventAbort,
+ TouchEventDown,
+ TouchEventUp,
+ TouchEventMove
+ } TouchEvent;
+
+ /*!
+ \brief Get an instance of the touch input manager
+ */
+ static CTouchInput &Get();
+
+ /*!
+ \brief Register a touch input handler
+
+ There can only be one touch input handler
+ active.
+
+ \param touchHandler An instance of a touch handler implementing the ITouchHandler interface
+ */
+ void RegisterHandler(ITouchHandler *touchHandler);
+ /*!
+ \brief Unregister the touch handler
+ */
+ void UnregisterHandler();
+
+ /*!
+ \brief Set the timeout after which a touch turns into a touch hold
+ \param timeout Timeout in milliseconds
+ */
+ void SetTouchHoldTimeout(int32_t timeout);
+
+ /*!
+ \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
+ */
+ bool Handle(TouchEvent event, float x, float y, int64_t time, int32_t pointer = 0, float size = 0.0f);
+
+ /*!
+ \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
+ */
+ bool Update(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
+ CTouchInput();
+ CTouchInput(const CTouchInput&);
+ CTouchInput const& operator=(CTouchInput const&);
+ virtual ~CTouchInput();
+
+ void saveLastTouch();
+
+ void handleMultiTouchGesture();
+ void handleZoomPinch();
+
+ // implementation of ITimerCallback
+ virtual void OnTimeout();
+
+ // implementation of ITouchHandler
+ 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 OnMultiTouchStart(float x, float y, int32_t pointers = 2);
+ 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 OnMultiTouchEnd(float x, float y, int32_t pointers = 2);
+
+ virtual bool OnTouchGesturePanStart(float x, float y);
+ virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+ virtual bool OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY);
+
+ // convenience events
+ virtual void OnSingleTap(float x, float y);
+ virtual void OnSingleLongPress(float x, float y);
+ virtual void OnDoubleTap(float x1, float y1, float x2, float y2);
+ virtual void OnDoubleLongPress(float x1, float y1, float x2, float y2);
+ virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor);
+
+ CCriticalSection m_critical;
+
+ int32_t m_holdTimeout;
+ ITouchHandler *m_handler;
+ CTimer *m_holdTimer;
+
+ class Touch : public CVector {
+ public:
+ Touch() { reset(); }
+ virtual ~Touch() { }
+
+ virtual void reset() { CVector::reset(); time = -1; }
+
+ bool valid() const { return x >= 0.0f && y >= 0.0f && time >= 0; }
+ void copy(const Touch &other) { x = other.x; y = other.y; time = other.time; }
+
+ int64_t time; // in nanoseconds
+ };
+
+ class Pointer {
+ public:
+ Pointer() { reset(); }
+
+ bool valid() const { return down.valid(); }
+ void reset() { down.reset(); last.reset(); moving = false; size = 0.0f; }
+
+ bool velocity(float &velocityX, float &velocityY, bool fromLast = true)
+ {
+ Touch &from = last;
+ if (!fromLast)
+ from = down;
+
+ velocityX = 0.0f; // number of pixels per second
+ velocityY = 0.0f; // number of pixels per second
+
+ int64_t timeDiff = current.time - from.time;
+ if (timeDiff <= 0)
+ return false;
+
+ velocityX = ((current.x - from.x) * 1000000000) / timeDiff;
+ velocityY = ((current.y - from.y) * 1000000000) / timeDiff;
+ return true;
+ }
+
+ Touch down;
+ Touch last;
+ Touch current;
+ bool moving;
+ float size;
+ };
+
+ Pointer m_pointers[TOUCH_MAX_POINTERS];
+
+ 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;
+
+ TouchGestureState m_gestureState;
+ TouchGestureState m_gestureStateOld;
+
+ void setGestureState(TouchGestureState gestureState) { m_gestureStateOld = m_gestureState; m_gestureState = gestureState; }
+};
Please sign in to comment.
Something went wrong with that request. Please try again.