diff options
Diffstat (limited to 'xbmc/input/TouchInput.h')
-rw-r--r-- | xbmc/input/TouchInput.h | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/xbmc/input/TouchInput.h b/xbmc/input/TouchInput.h new file mode 100644 index 0000000000..a926b99385 --- /dev/null +++ b/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; } +}; |