michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef InputData_h__ michael@0: #define InputData_h__ michael@0: michael@0: #include "nsDebug.h" michael@0: #include "nsPoint.h" michael@0: #include "nsTArray.h" michael@0: #include "Units.h" michael@0: #include "mozilla/EventForwards.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: michael@0: enum InputType michael@0: { michael@0: MULTITOUCH_INPUT, michael@0: PINCHGESTURE_INPUT, michael@0: TAPGESTURE_INPUT michael@0: }; michael@0: michael@0: class MultiTouchInput; michael@0: class PinchGestureInput; michael@0: class TapGestureInput; michael@0: michael@0: // This looks unnecessary now, but as we add more and more classes that derive michael@0: // from InputType (eventually probably almost as many as *Events.h has), it michael@0: // will be more and more clear what's going on with a macro that shortens the michael@0: // definition of the RTTI functions. michael@0: #define INPUTDATA_AS_CHILD_TYPE(type, enumID) \ michael@0: const type& As##type() const \ michael@0: { \ michael@0: NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \ michael@0: return (const type&) *this; \ michael@0: } michael@0: michael@0: /** Base input data class. Should never be instantiated. */ michael@0: class InputData michael@0: { michael@0: public: michael@0: InputType mInputType; michael@0: // Time in milliseconds that this data is relevant to. This only really michael@0: // matters when this data is used as an event. We use uint32_t instead of michael@0: // TimeStamp because it is easier to convert from WidgetInputEvent. The time michael@0: // is platform-specific but it in the case of B2G and Fennec it is since michael@0: // startup. michael@0: uint32_t mTime; michael@0: michael@0: Modifiers modifiers; michael@0: michael@0: INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT) michael@0: INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT) michael@0: INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT) michael@0: michael@0: InputData() michael@0: { michael@0: } michael@0: michael@0: protected: michael@0: InputData(InputType aInputType, uint32_t aTime, Modifiers aModifiers) michael@0: : mInputType(aInputType), michael@0: mTime(aTime), michael@0: modifiers(aModifiers) michael@0: { michael@0: michael@0: michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * Data container for a single touch input. Similar to dom::Touch, but used in michael@0: * off-main-thread situations. This is more for just storing touch data, whereas michael@0: * dom::Touch is more useful for dispatching through the DOM (which can only michael@0: * happen on the main thread). dom::Touch also bears the problem of storing michael@0: * pointers to nsIWidget instances which can only be used on the main thread, michael@0: * so if instead we used dom::Touch and ever set these pointers michael@0: * off-main-thread, Bad Things Can Happen(tm). michael@0: * michael@0: * Note that this doesn't inherit from InputData because this itself is not an michael@0: * event. It is only a container/struct that should have any number of instances michael@0: * within a MultiTouchInput. michael@0: * michael@0: * fixme/bug 775746: Make dom::Touch inherit from this class. michael@0: */ michael@0: class SingleTouchData michael@0: { michael@0: public: michael@0: SingleTouchData(int32_t aIdentifier, michael@0: ScreenIntPoint aScreenPoint, michael@0: ScreenSize aRadius, michael@0: float aRotationAngle, michael@0: float aForce) michael@0: : mIdentifier(aIdentifier), michael@0: mScreenPoint(aScreenPoint), michael@0: mRadius(aRadius), michael@0: mRotationAngle(aRotationAngle), michael@0: mForce(aForce) michael@0: { michael@0: michael@0: michael@0: } michael@0: michael@0: SingleTouchData() michael@0: { michael@0: } michael@0: michael@0: // A unique number assigned to each SingleTouchData within a MultiTouchInput so michael@0: // that they can be easily distinguished when handling a touch start/move/end. michael@0: int32_t mIdentifier; michael@0: michael@0: // Point on the screen that the touch hit, in device pixels. They are michael@0: // coordinates on the screen. michael@0: ScreenIntPoint mScreenPoint; michael@0: michael@0: // Radius that the touch covers, i.e. if you're using your thumb it will michael@0: // probably be larger than using your pinky, even with the same force. michael@0: // Radius can be different along x and y. For example, if you press down with michael@0: // your entire finger vertically, the y radius will be much larger than the x michael@0: // radius. michael@0: ScreenSize mRadius; michael@0: michael@0: float mRotationAngle; michael@0: michael@0: // How hard the screen is being pressed. michael@0: float mForce; michael@0: }; michael@0: michael@0: /** michael@0: * Similar to WidgetTouchEvent, but for use off-main-thread. Also only stores a michael@0: * screen touch point instead of the many different coordinate spaces michael@0: * WidgetTouchEvent stores its touch point in. This includes a way to initialize michael@0: * itself from a WidgetTouchEvent by copying all relevant data over. Note that michael@0: * this copying from WidgetTouchEvent functionality can only be used on the main michael@0: * thread. michael@0: * michael@0: * Stores an array of SingleTouchData. michael@0: */ michael@0: class MultiTouchInput : public InputData michael@0: { michael@0: public: michael@0: enum MultiTouchType michael@0: { michael@0: MULTITOUCH_START, michael@0: MULTITOUCH_MOVE, michael@0: MULTITOUCH_END, michael@0: MULTITOUCH_ENTER, michael@0: MULTITOUCH_LEAVE, michael@0: MULTITOUCH_CANCEL michael@0: }; michael@0: michael@0: MultiTouchInput(MultiTouchType aType, uint32_t aTime, Modifiers aModifiers) michael@0: : InputData(MULTITOUCH_INPUT, aTime, aModifiers), michael@0: mType(aType) michael@0: { michael@0: michael@0: michael@0: } michael@0: michael@0: MultiTouchInput() michael@0: { michael@0: } michael@0: michael@0: MultiTouchInput(const WidgetTouchEvent& aTouchEvent); michael@0: michael@0: // This conversion from WidgetMouseEvent to MultiTouchInput is needed because michael@0: // on the B2G emulator we can only receive mouse events, but we need to be michael@0: // able to pan correctly. To do this, we convert the events into a format that michael@0: // the panning code can handle. This code is very limited and only supports michael@0: // SingleTouchData. It also sends garbage for the identifier, radius, force michael@0: // and rotation angle. michael@0: MultiTouchInput(const WidgetMouseEvent& aMouseEvent); michael@0: michael@0: MultiTouchType mType; michael@0: nsTArray mTouches; michael@0: }; michael@0: michael@0: /** michael@0: * Encapsulation class for pinch events. In general, these will be generated by michael@0: * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and michael@0: * determining whether or not the user was trying to do a gesture. michael@0: */ michael@0: class PinchGestureInput : public InputData michael@0: { michael@0: public: michael@0: enum PinchGestureType michael@0: { michael@0: PINCHGESTURE_START, michael@0: PINCHGESTURE_SCALE, michael@0: PINCHGESTURE_END michael@0: }; michael@0: michael@0: PinchGestureInput(PinchGestureType aType, michael@0: uint32_t aTime, michael@0: const ScreenPoint& aFocusPoint, michael@0: float aCurrentSpan, michael@0: float aPreviousSpan, michael@0: Modifiers aModifiers) michael@0: : InputData(PINCHGESTURE_INPUT, aTime, aModifiers), michael@0: mType(aType), michael@0: mFocusPoint(aFocusPoint), michael@0: mCurrentSpan(aCurrentSpan), michael@0: mPreviousSpan(aPreviousSpan) michael@0: { michael@0: michael@0: michael@0: } michael@0: michael@0: PinchGestureType mType; michael@0: michael@0: // Center point of the pinch gesture. That is, if there are two fingers on the michael@0: // screen, it is their midpoint. In the case of more than two fingers, the michael@0: // point is implementation-specific, but can for example be the midpoint michael@0: // between the very first and very last touch. This is in device pixels and michael@0: // are the coordinates on the screen of this midpoint. michael@0: ScreenPoint mFocusPoint; michael@0: michael@0: // The distance in device pixels (though as a float for increased precision michael@0: // and because it is the distance along both the x and y axis) between the michael@0: // touches responsible for the pinch gesture. michael@0: float mCurrentSpan; michael@0: michael@0: // The previous |mCurrentSpan| in the PinchGestureInput preceding this one. michael@0: // This is only really relevant during a PINCHGESTURE_SCALE because when it is michael@0: // of this type then there must have been a history of spans. michael@0: float mPreviousSpan; michael@0: }; michael@0: michael@0: /** michael@0: * Encapsulation class for tap events. In general, these will be generated by michael@0: * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and michael@0: * determining whether or not the user was trying to do a gesture. michael@0: */ michael@0: class TapGestureInput : public InputData michael@0: { michael@0: public: michael@0: enum TapGestureType michael@0: { michael@0: TAPGESTURE_LONG, michael@0: TAPGESTURE_LONG_UP, michael@0: TAPGESTURE_UP, michael@0: TAPGESTURE_CONFIRMED, michael@0: TAPGESTURE_DOUBLE, michael@0: TAPGESTURE_CANCEL michael@0: }; michael@0: michael@0: TapGestureInput(TapGestureType aType, michael@0: uint32_t aTime, michael@0: const ScreenIntPoint& aPoint, michael@0: Modifiers aModifiers) michael@0: : InputData(TAPGESTURE_INPUT, aTime, aModifiers), michael@0: mType(aType), michael@0: mPoint(aPoint) michael@0: { michael@0: michael@0: michael@0: } michael@0: michael@0: TapGestureType mType; michael@0: ScreenIntPoint mPoint; michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif // InputData_h__