Bug 750974: Move basic pan/zoom logic into Gecko C++ r=cjones,roc sr=smaug[widget/]
This commit is contained in:
325
widget/InputData.h
Normal file
325
widget/InputData.h
Normal file
@@ -0,0 +1,325 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef InputData_h__
|
||||
#define InputData_h__
|
||||
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsDOMTouchEvent.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
||||
enum InputType
|
||||
{
|
||||
MULTITOUCH_INPUT,
|
||||
PINCHGESTURE_INPUT,
|
||||
TAPGESTURE_INPUT
|
||||
};
|
||||
|
||||
class MultiTouchInput;
|
||||
class PinchGestureInput;
|
||||
class TapGestureInput;
|
||||
|
||||
// This looks unnecessary now, but as we add more and more classes that derive
|
||||
// from InputType (eventually probably almost as many as nsGUIEvent.h has), it
|
||||
// will be more and more clear what's going on with a macro that shortens the
|
||||
// definition of the RTTI functions.
|
||||
#define INPUTDATA_AS_CHILD_TYPE(type, enumID) \
|
||||
const type& As##type() const \
|
||||
{ \
|
||||
NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \
|
||||
return (const type&) *this; \
|
||||
}
|
||||
|
||||
/** Base input data class. Should never be instantiated. */
|
||||
class InputData
|
||||
{
|
||||
public:
|
||||
InputType mInputType;
|
||||
// Time in milliseconds that this data is relevant to. This only really
|
||||
// matters when this data is used as an event. We use PRUint32 instead of
|
||||
// TimeStamp because it is easier to convert from nsInputEvent. The time is
|
||||
// platform-specific but it in the case of B2G and Fennec it is since startup.
|
||||
PRUint32 mTime;
|
||||
|
||||
INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
|
||||
|
||||
protected:
|
||||
InputData(InputType aInputType, PRUint32 aTime)
|
||||
: mInputType(aInputType),
|
||||
mTime(aTime)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Data container for a single touch input. Similar to nsDOMTouch, but used in
|
||||
* off-main-thread situations. This is more for just storing touch data, whereas
|
||||
* nsDOMTouch derives from nsIDOMTouch so it is more useful for dispatching
|
||||
* through the DOM (which can only happen on the main thread). nsDOMTouch also
|
||||
* bears the problem of storing pointers to nsIWidget instances which can only
|
||||
* be used on the main thread, so if instead we used nsDOMTouch and ever set
|
||||
* these pointers off-main-thread, Bad Things Can Happen(tm).
|
||||
*
|
||||
* Note that this doesn't inherit from InputData because this itself is not an
|
||||
* event. It is only a container/struct that should have any number of instances
|
||||
* within a MultiTouchInput.
|
||||
*
|
||||
* fixme/bug 775746: Make nsDOMTouch inherit from this class.
|
||||
*/
|
||||
class SingleTouchData
|
||||
{
|
||||
public:
|
||||
SingleTouchData(PRInt32 aIdentifier,
|
||||
nsIntPoint aScreenPoint,
|
||||
nsIntPoint aRadius,
|
||||
float aRotationAngle,
|
||||
float aForce)
|
||||
: mIdentifier(aIdentifier),
|
||||
mScreenPoint(aScreenPoint),
|
||||
mRadius(aRadius),
|
||||
mRotationAngle(aRotationAngle),
|
||||
mForce(aForce)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// A unique number assigned to each SingleTouchData within a MultiTouchInput so
|
||||
// that they can be easily distinguished when handling a touch start/move/end.
|
||||
PRInt32 mIdentifier;
|
||||
|
||||
// Point on the screen that the touch hit, in device pixels. They are
|
||||
// coordinates on the screen.
|
||||
nsIntPoint mScreenPoint;
|
||||
|
||||
// Radius that the touch covers, i.e. if you're using your thumb it will
|
||||
// probably be larger than using your pinky, even with the same force.
|
||||
// Radius can be different along x and y. For example, if you press down with
|
||||
// your entire finger vertically, the y radius will be much larger than the x
|
||||
// radius.
|
||||
nsIntPoint mRadius;
|
||||
|
||||
float mRotationAngle;
|
||||
|
||||
// How hard the screen is being pressed.
|
||||
float mForce;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to nsTouchEvent, but for use off-main-thread. Also only stores a
|
||||
* screen touch point instead of the many different coordinate spaces nsTouchEvent
|
||||
* stores its touch point in. This includes a way to initialize itself from an
|
||||
* nsTouchEvent by copying all relevant data over. Note that this copying from
|
||||
* nsTouchEvent functionality can only be used on the main thread.
|
||||
*
|
||||
* Stores an array of SingleTouchData.
|
||||
*/
|
||||
class MultiTouchInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum MultiTouchType
|
||||
{
|
||||
MULTITOUCH_START,
|
||||
MULTITOUCH_MOVE,
|
||||
MULTITOUCH_END,
|
||||
MULTITOUCH_ENTER,
|
||||
MULTITOUCH_LEAVE,
|
||||
MULTITOUCH_CANCEL
|
||||
};
|
||||
|
||||
MultiTouchInput(MultiTouchType aType, PRUint32 aTime)
|
||||
: InputData(MULTITOUCH_INPUT, aTime),
|
||||
mType(aType)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
MultiTouchInput(const nsTouchEvent& aTouchEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aTouchEvent.time)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(),
|
||||
"Can only copy from nsTouchEvent on main thread");
|
||||
|
||||
switch (aTouchEvent.message) {
|
||||
case NS_TOUCH_START:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case NS_TOUCH_MOVE:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case NS_TOUCH_END:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
case NS_TOUCH_ENTER:
|
||||
mType = MULTITOUCH_ENTER;
|
||||
break;
|
||||
case NS_TOUCH_LEAVE:
|
||||
mType = MULTITOUCH_LEAVE;
|
||||
break;
|
||||
case NS_TOUCH_CANCEL:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aTouchEvent.touches.Length(); i++) {
|
||||
nsDOMTouch* domTouch = (nsDOMTouch*)(aTouchEvent.touches[i].get());
|
||||
|
||||
// Extract data from weird interfaces.
|
||||
PRInt32 identifier, radiusX, radiusY;
|
||||
float rotationAngle, force;
|
||||
domTouch->GetIdentifier(&identifier);
|
||||
domTouch->GetRadiusX(&radiusX);
|
||||
domTouch->GetRadiusY(&radiusY);
|
||||
domTouch->GetRotationAngle(&rotationAngle);
|
||||
domTouch->GetForce(&force);
|
||||
|
||||
SingleTouchData data(identifier,
|
||||
domTouch->mRefPoint,
|
||||
nsIntPoint(radiusX, radiusY),
|
||||
rotationAngle,
|
||||
force);
|
||||
|
||||
mTouches.AppendElement(data);
|
||||
}
|
||||
}
|
||||
|
||||
// This conversion from nsMouseEvent to MultiTouchInput is needed because on
|
||||
// the B2G emulator we can only receive mouse events, but we need to be able
|
||||
// to pan correctly. To do this, we convert the events into a format that the
|
||||
// panning code can handle. This code is very limited and only supports
|
||||
// SingleTouchData. It also sends garbage for the identifier, radius, force
|
||||
// and rotation angle.
|
||||
MultiTouchInput(const nsMouseEvent& aMouseEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aMouseEvent.time)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(),
|
||||
"Can only copy from nsMouseEvent on main thread");
|
||||
switch (aMouseEvent.message) {
|
||||
case NS_MOUSE_BUTTON_DOWN:
|
||||
mType = MULTITOUCH_START;
|
||||
break;
|
||||
case NS_MOUSE_MOVE:
|
||||
mType = MULTITOUCH_MOVE;
|
||||
break;
|
||||
case NS_MOUSE_BUTTON_UP:
|
||||
mType = MULTITOUCH_END;
|
||||
break;
|
||||
// The mouse pointer has been interrupted in an implementation-specific
|
||||
// manner, such as a synchronous event or action cancelling the touch, or a
|
||||
// touch point leaving the document window and going into a non-document
|
||||
// area capable of handling user interactions.
|
||||
case NS_MOUSE_EXIT:
|
||||
mType = MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Did not assign a type to a MultiTouchInput");
|
||||
break;
|
||||
}
|
||||
|
||||
mTouches.AppendElement(SingleTouchData(0,
|
||||
aMouseEvent.refPoint,
|
||||
nsIntPoint(1, 1),
|
||||
180.0f,
|
||||
1.0f));
|
||||
}
|
||||
|
||||
MultiTouchType mType;
|
||||
nsTArray<SingleTouchData> mTouches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pinch events. In general, these will be generated by
|
||||
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
|
||||
* determining whether or not the user was trying to do a gesture.
|
||||
*/
|
||||
class PinchGestureInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum PinchGestureType
|
||||
{
|
||||
PINCHGESTURE_START,
|
||||
PINCHGESTURE_SCALE,
|
||||
PINCHGESTURE_END
|
||||
};
|
||||
|
||||
PinchGestureInput(PinchGestureType aType,
|
||||
PRUint32 aTime,
|
||||
const nsIntPoint& aFocusPoint,
|
||||
float aCurrentSpan,
|
||||
float aPreviousSpan)
|
||||
: InputData(PINCHGESTURE_INPUT, aTime),
|
||||
mType(aType),
|
||||
mFocusPoint(aFocusPoint),
|
||||
mCurrentSpan(aCurrentSpan),
|
||||
mPreviousSpan(aPreviousSpan)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
PinchGestureType mType;
|
||||
|
||||
// Center point of the pinch gesture. That is, if there are two fingers on the
|
||||
// screen, it is their midpoint. In the case of more than two fingers, the
|
||||
// point is implementation-specific, but can for example be the midpoint
|
||||
// between the very first and very last touch. This is in device pixels and
|
||||
// are the coordinates on the screen of this midpoint.
|
||||
nsIntPoint mFocusPoint;
|
||||
|
||||
// The distance in device pixels (though as a float for increased precision
|
||||
// and because it is the distance along both the x and y axis) between the
|
||||
// touches responsible for the pinch gesture.
|
||||
float mCurrentSpan;
|
||||
|
||||
// The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
|
||||
// This is only really relevant during a PINCHGESTURE_SCALE because when it is
|
||||
// of this type then there must have been a history of spans.
|
||||
float mPreviousSpan;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for tap events. In general, these will be generated by
|
||||
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
|
||||
* determining whether or not the user was trying to do a gesture.
|
||||
*/
|
||||
class TapGestureInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum TapGestureType
|
||||
{
|
||||
TAPGESTURE_LONG,
|
||||
TAPGESTURE_UP,
|
||||
TAPGESTURE_CONFIRMED,
|
||||
TAPGESTURE_DOUBLE,
|
||||
TAPGESTURE_CANCEL
|
||||
};
|
||||
|
||||
TapGestureInput(TapGestureType aType, PRUint32 aTime, const nsIntPoint& aPoint)
|
||||
: InputData(TAPGESTURE_INPUT, aTime),
|
||||
mType(aType),
|
||||
mPoint(aPoint)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
TapGestureType mType;
|
||||
nsIntPoint mPoint;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // InputData_h__
|
||||
Reference in New Issue
Block a user